I have a class Library https://github.com/trydis/FIFA-Ultimate-Team-2014-Toolkit I want to make a wrapper for, instead of just calling FutClient I want to make a FutClientWrapper where I can handle exceptions, reloggin and loggin the interface I want to wrap is https://github.com/trydis/FIFA-Ultimate-Team-2014-Toolkit/blob/master/UltimateTeam.Toolkit/IFutClient.cs
So I made http://pastebin.com/0EJdCbbr
Code snippet
public async Task<AuctionResponse> SearchAsync(SearchParameters searchParameters)
{
return await Invoke(f => f.SearchAsync(searchParameters), searchParameters);
}
public async Task<AuctionResponse> PlaceBidAsync(AuctionInfo auctionInfo, uint bidAmount = 0)
{
return await Invoke(f => f.PlaceBidAsync(auctionInfo, bidAmount), auctionInfo);
}
public async Task<Item> GetItemAsync(long resourceId)
{
return await Invoke(f => f.GetItemAsync(resourceId), resourceId);
}
public TResult Invoke<TResult>(Func<FutClient, TResult> func, object requestDetails = null,
[CallerMemberName] string exceptionMessage = null)
{
try
{
if (LastException + new TimeSpan(0, 0, 30) < DateTime.Now)
{
TResult result = func(_futClient);
return result;
}
}
catch (Exception e)
{
Here I try to wrap and catch any exception thrown inside the Futclient, but instead I get a null exception in for example this line
return await Invoke(f => f.GetItemAsync(resourceId), resourceId);
And it seems its because my
TResult result = func(_futClient);
return result;
Is not run async and it just returns an empty response (All null values)
So I changed it to look like http://pastebin.com/pJkPr2xN
Code snippet:
public async Task<AuctionResponse> GetTradePileAsync()
{
return await NewInvoke<AuctionResponse>(new Task<object>(() => _futClient.GetTradePileAsync()));
}
public async Task<WatchlistResponse> GetWatchlistAsync()
{
return await NewInvoke<WatchlistResponse>(new Task<object>(() => _futClient.GetWatchlistAsync()));
}
public async Task<TResult> NewInvoke<TResult>(Task<object> taskToRun) where TResult : class
{
try
{
taskToRun.Start();
Task.WaitAll(taskToRun);
return taskToRun.Result as TResult;
}
catch (AggregateException ex)
{
//ex.InnerException
return null;
}
catch (Exception e)
{
return null;
}
}
But also here I get exceptions outside my invoke method
So how should I make this so it handles both Task and Task as a response type and takes x number of arguments
And it should then throw any exceptions inside the Invoke method so I only have one place where exceptions needs to be caught
You must await inside the try block before you return, otherwise the exception will not be cought by the catch. Your first attempt was actually closer to the correct way to do it.
public async Task<TResult> Invoke<TResult>(Func<FutClient, Task<TResult>> func, object requestDetails = null,
[CallerMemberName] string exceptionMessage = null)
{
try
{
if (LastException + new TimeSpan(0, 0, 30) < DateTime.Now)
{
TResult result = await func(_futClient).ConfigureAwait(false); //Here we both await for the result and set `ConfigureAwait` to false so we don't need to waist extra time trying to marshal back on to the original Synchronization context as we have no need for it for the rest of the method.
return result;
}
}
catch (Exception e)
{
//...
You then just use it like the following
public Task<AuctionResponse> PlaceBidAsync(AuctionInfo auctionInfo, uint bidAmount = 0)
{
return Invoke(f => f.PlaceBidAsync(auctionInfo, bidAmount), auctionInfo);
}
There is no need to await in this outer function, you can just directly return the Task returned by Invoke
Related
I'm trying to write a recursion method to retrieve the parent of a object (and that parent etc). This in itself isn't a problem but the calls are async which result in the following error:
The body of '.....Recursive(string)' cannot be an iterator block because 'Task<IEnumerable>' is not an iterator interface type [...]csharp(CS1624)
The code:
private async Task<IEnumerable<string>> Recursive(string objectId)
{
var result = await GetParent(objectId);
if (result?.Length > 0)
{
yield return result;
await Recursive(objectId);
}
}
private async Task<string> GetParent(string objectId)
{
await Task.Run(() => { return $"{objectId}/parent"; });
}
I have also tried IAsyncEnumerable but that resulted in the folllowing error:
'IAsyncEnumerable' does not contain a definition for 'GetAwaiter' and no accessible extension method 'GetAwaiter' accepting a first argument of type 'IAsyncEnumerable' could be found (are you missing a using directive or an assembly reference?) [...]csharp(CS1061)
private async IAsyncEnumerable<string> Recursive(string objectId)
{
var result = await GetParent(objectId);
if (result?.Length > 0)
{
yield return result;
await Recursive(objectId);
}
}
private async Task<string> GetParent(string objectId)
{
await Task.Run(() => { return $"{objectId}/parent"; });
}
I'm going to write a while loop to get this to work. But I'm interested if this is possible at all.
Update 2:
Ok, I think I got it. Thanks guys.
private async IAsyncEnumerable<string> Recursive(string objectId)
{
var result = await GetParent(objectId);
if (result?.Length > 0)
{
yield return result;
await foreach (var r2 in Recursive(objectId))
{
yield return r2;
}
}
}
private async Task<string> GetParent(string objectId)
{
await Task.Run(() => { return $"{objectId}/parent"; });
}
The current code wouldn't compile even if it was synchronous, and the result was IEnumerable<string>. The results of Recursive are never returned. It's not possible to just return an IEnumerable from an iterator either.
This code would work. Whether it does anything useful is another matter :
private IEnumerable<string> Recursive(string objectId)
{
var result = GetParent(objectId);
if (!string.IsNullOrEmpty(result))
{
yield return result;
foreach(var r in Recursive(result))
{
yield return r;
}
}
}
private string GetParent(string objectId)
{
return $"{objectId}/parent";
}
Getting it to work asynchronously only needs changing to IAsyncEnumerable and using await:
private async IAsyncEnumerable<string> Recursive(string objectId)
{
var result = await GetParent(objectId);
if (!string.IsNullOrEmpty(result))
{
yield return result;
await foreach(var r in Recursive(result))
{
yield return r;
}
}
}
private Task<string> GetParent(string objectId)
{
return Task.FromResult($"{objectId}/parent");
}
I want to convert my code to async but i get error converting types,how can i turn this code to async?
public IQueryable<MyProject.Models.Campaign> Where(System.Linq.Expressions.Expression<Func<MyProject.Models.Campaign, bool>> predicate)
{
try
{
return db.Campaigns.Where(predicate);
}
catch
{
return null;
}
}
i found out how to do that , the problem was i had to change IQueryable to IList.
public async Task<IList<MyProject.Models.Campaign>> WhereAsync(System.Linq.Expressions.Expression<Func<MyProject.Models.Campaign, bool>> predicate)
{
try
{
return await db.Campaigns.Where(predicate).ToListAsync();
}
catch
{
return null;
}
}
I am getting an exception on the Do Method of Rhino Mock.
System.InvalidOperationException : The delegate return value should be
assignable from MediaPlayerImpl.ScreenControl.ScreenCommunicatorState
I am not very clear how to resolve it. Below is my code. Its quite to simple to understand.
var mockCommunicator = Rhino.Mocks.MockRepository.GenerateStrictMock<IScreenCommunicator>();
ManualResetEvent screenTurnedOff = new ManualResetEvent(false);
mockCommunicator.Expect(c => c.TurnScreenOff(default(ScreenCommunicatorState))).IgnoreArguments()
.Do(new Action(() => screenTurnedOff.Set()));
public override ScreenCommunicatorState TurnScreenOn(ScreenCommunicatorState state)
{
state = state ?? new ScreenCommunicatorState { isScreenOn = false };
if (state.isScreenOn)
{
// Try and Get the screen power state
// ....
Task<byte[]> requestTask = SendRequest(CommandSequences.GetPowerStatus);
var isPowerOn = InterpretScreenPowerStatusMessage(requestTask);
if (isPowerOn.Value)
{
// Do nothing
}
else if (!isPowerOn.Value)
{
SendCommandSequence(CommandSequences.PowerOn);
}
else if (isPowerOn == null)
{
SendCommandSequence(CommandSequences.PowerOn);
}
// NO
}
state.isScreenOn = true;
Task<bool?> screenTurnedOnTask = IsScreenTurnedOn();
Func<Task<bool?>, Task> doSomeWork = TurnScreenOnAndRectifyScreenInputSource;
Task<Task> turnScreenOnIfNecessaryTask = screenTurnedOnTask.ContinueWith(doSomeWork, TaskContinuationOptions.NotOnFaulted);
Task unwrapped = turnScreenOnIfNecessaryTask.Unwrap();
try
{
unwrapped.Wait(); // This will thrown an exception if it's faulted, which is what we want
}
catch (AggregateException aggregateException)
{
if (aggregateException.InnerExceptions.Count() == 1)
{
throw aggregateException.InnerExceptions[0];
}
else
{
throw;
}
}
return state;
}
I had to use and Func Delegate in order to resolve the issue.
.Do(new Func<ScreenCommunicatorState,ScreenCommunicatorState>((id) => {
screenTurnedOff.Set();
return new ScreenCommunicatorState();
}))
.Return(new ScreenCommunicatorState());
Do you know a better way (more pretty) than below to throw an exception?
public long GetPlaylistId(long songInPlaylistId)
{
var songInPlaylist = service.GetById(songInPlaylistId);
return songInPlaylist
.With(x => x.Playlist)
.ReturnValueOrException(x => x.Id,
new ArgumentException(
"Bad argument 'songInPlaylistId'"));
}
Monadic extension methods:
public static TResult With<TInput, TResult>(this TInput obj,
Func<TInput, TResult> evaluator)
where TInput : class
where TResult : class
{
return obj == null ? null : evaluator(obj);
}
public static TResult ReturnValueOrException<TInput, TResult>(
this TInput obj, Func<TInput, TResult> evaluator, Exception exception)
where TInput : class
{
if (obj != null)
{
return evaluator(obj);
}
throw exception;
}
If it is valid to try to get the playlist for something that doesn't have a playlist, then you should not throw an exception but should just return a special value that means "not found" instead (for example, 0 or -1 depending on how your playlist IDs work).
Alternatively you could write a TryGetPlaylistId() method which works in a similar way to Microsoft's TryXXX() methods (e.g. SortedList.TryGetValue()), for example:
public bool TryGetPlaylistId(long songInPlaylistId, out long result)
{
result = 0;
var songInPlaylist = service.GetById(songInPlaylistId);
if (songInPlaylist == null)
return false;
if (songInPlaylist.Playlist == null)
return false;
result = songInPlaylist.Playlist.Id;
return true;
}
A small problem with this approach is that you are obscuring information that might be of use when trying to diagnose issues. Perhaps adding Debug.WriteLine() or some other form of logging would be of use. The point being, you can't differentiate between the case where the playlist ID is not found, and the case where it is found but doesn't contain a playlist.
Otherwise, you could throw an exception which has a more informative message, for example:
public long GetPlaylistId(long songInPlaylistId)
{
var songInPlaylist = service.GetById(songInPlaylistId);
if (songInPlaylist == null)
throw new InvalidOperationException("songInPlaylistId not found: " + songInPlaylistId);
if (songInPlaylist.Playlist == null)
throw new InvalidOperationException("Playlist for ID " + songInPlaylistId " has no playlist: ");
return songInPlaylist.Playlist.Id;
}
It might be the case that it is valid to not find the song in the playlist, but it is NOT valid to find one which does not have a playlist, in which case you would return a special value in the first case and throw an exception in the second case, for example:
public long GetPlaylistId(long songInPlaylistId)
{
var songInPlaylist = service.GetById(songInPlaylistId);
if (songInPlaylist == null)
return -1; // -1 means "playlist not found".
if (songInPlaylist.Playlist == null)
throw new InvalidOperationException("Playlist for ID " + songInPlaylistId " has no playlist: ");
return songInPlaylist.Playlist.Id;
}
In any case, I personally think that your extension methods are just obscuring the code.
try{
if (obj != null)
{
return evaluator(obj);
}
}
catch(Exception ex)
{
throw;
}
return obj;
You should not throw error unless caught in to some. Better return null in the given case and handle it in your calling code:
And what will happen if I have more than one such ambiguous methods in my class? It's very difficult to invent different rules for any method. You will be confused in the end.
What do you think about this solution?
public class ApplicationResponse
{
public IList<string> Errors { get; set; }
public dynamic Data { get; set; }
public bool HasErrors()
{
return Errors != null && Errors.Any();
}
}
public ApplicationResponse GetPlaylistId(long songInPlaylistId)
{
var songInPlaylist = service.GetById(songInPlaylistId);
if (songInPlaylist == null)
{
return new ApplicationResponse { Errors = new[] { "Song was not found." } };
}
if (songInPlaylist.Playlist == null)
{
return new ApplicationResponse { Errors = new[] { "Playlist was not found." } };
}
return new ApplicationResponse { Data = songInPlaylist.Playlist.Id };
}
public HttpResponseMessage SomeRequest([FromUri] songInPlaylistId)
{
var response = appService.GetPlaylistId(long songInPlaylistId);
if (response.HasErrors())
{
// reply with error status
}
// reply with ok status
}
In such case I can send all the errors to a client.
I would like to provide encapsulation of actions/methods generically. I think this should be possible in C# but I'm not able to produce it so it compiles...
The following briefly demonstrates what I want. Is this possible somehow, perhaps by generalizing the class?
Required is:
I want to execute the function/action (see method type) and 'do something' when an error occurs
I want to return the value of the function if the method is a function (otherwise return void if possible)
I want to 'do something' if the return type of the function is a boolean and the value is false.
public class Encapsulator {
private Action _action;
private Func<T> _function;
private MethodType _type; //Action || Function
public Encapsulator(Action action) {
this._action = action;
this._type = MethodType.Action;
}
public Encapsulator(Func<T> func) { //This is not accepted
this._function = func;
this._type = MethodType.Function;
}
public void Execute() {
try {
this._action();
}
catch(Exception ex) {
//do something
throw;
}
}
public T Execute<T>() {
try {
var r = this._function();
if(typeof(r) == bool) {
if(!r)
//do something
}
return r;
} catch(Exception ex) {
//do something
throw;
}
}
}
Your second constructor won't compile because their are no generics applied to the type at the higher level:
public Encapsulator<T>
{
public Encapsulator(Func<T> func)
{
this._function = func;
this._type = MethodType.Function;
}
}
Instead of just introducing new things within the parameters of a method, essentially, we need to specify that those things are 'available' for utilisation in the definitions. So, for instance, if you were trying to add a specific generic method, you could apply it as you have done, but would instead need to do (something which you demonstrate with the Execute method):
public void MyGenericMethod<T>(Func<T> func)
{
}
Noting the first T, we're specifying the existence of T, as such.
There are possibly more issues at hand with your code here, but I believe, on first glance, this to be the crux of the problems you're having.
As for returning variable types, the best you might hope for is returning a plain old object. Or, making use of the dynamic type, however, I wouldn't have thought this would be the way to go and wouldn't recommend it; you can't flip return type from an actual type to a void, though.
New Approach: The action Encapsulator will now return a dummy result (always true).
public class Encapsulator
{
public static Encapsulator<bool> CreateEncapsulator(Action action)
{
return new Encapsulator<bool>(() =>
{
action();
return true;
});
}
public static Encapsulator<T> CreateEncapsulator<T>(Func<T> func)
{
return new Encapsulator<T>(func);
}
}
public class Encapsulator<T>
{
private Func<T> _function;
internal Encapsulator(Func<T> func)
{
this._function = func;
}
public T Execute()
{
try
{
object res = this._function();
Nullable<bool> bres = res as Nullable<bool>;
if (bres.HasValue)
{
if (!bres.Value)
Console.WriteLine("NOT TRUE!");
//do something
}
return (T)res;
}
catch (Exception ex)
{
//do something
throw;
}
}
}
Calling the code:
var withDummyReturn = Encapsulator.CreateEncapsulator(() => Console.WriteLine("Great"));
withDummyReturn.Execute();
var withReturn = Encapsulator.CreateEncapsulator<bool>(() => true);
bool res = withReturn.Execute();