Skip to content

Instantly share code, notes, and snippets.

@coldacid
Created December 22, 2012 03:12
Show Gist options
  • Save coldacid/4357319 to your computer and use it in GitHub Desktop.
Save coldacid/4357319 to your computer and use it in GitHub Desktop.
Using the `async`/`await` keywords in C# makes it a lot easier to write asychronous code, which is very important for people working with Windows Phone or Windows 8. These keywords work with the Task Asynchronous Pattern (TAP) which is built around the `System.Threading.Tasks.Task` class, and which has an adaptor, `TaskCompletionSource<>`, for d…
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Scoreloop.CoreSocial.API;
using Scoreloop.CoreSocial.API.Model;
using System.Threading.Tasks;
using ScoreloopGame = Scoreloop.CoreSocial.API.Model.Game;
namespace Taptics
{
static class ScoreloopAsyncHelper
{
#region IRequestController handler management
private static bool IsInstanceOfGenericType(this Type @this, object o)
{
Type type = o.GetType();
while (type != null)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == @this)
return true;
type = type.BaseType;
}
return false;
}
private static Action SetupRequestHandlers(IRequestController controller, object taskCompletionSource, Action callbackRemoval = null)
{
var tcsType = typeof(TaskCompletionSource<>);
if (!tcsType.IsInstanceOfGenericType(taskCompletionSource))
throw new ArgumentException("taskCompletionSource must be of TaskCompletionSource<>");
var mTrySetException = tcsType.GetMethod("TrySetException", new Type[] { typeof(Exception) });
var mTrySetCancelled = tcsType.GetMethod("TrySetCancelled");
EventHandler<RequestControllerEventArgs<IRequestController>> requestFailedHandler = null;
EventHandler<RequestControllerEventArgs<IRequestController>> requestCancelledHandler = null;
Action removeHandlers = () =>
{
RemoveRequestHandlers(controller, requestFailedHandler, requestCancelledHandler);
if (callbackRemoval != null)
callbackRemoval();
};
requestFailedHandler = (s, e) =>
{
removeHandlers();
mTrySetException.Invoke(taskCompletionSource, new[] { e.Error.Exception });
};
requestCancelledHandler = (s, e) =>
{
removeHandlers();
mTrySetCancelled.Invoke(taskCompletionSource, null);
};
controller.RequestFailed += requestFailedHandler;
controller.RequestCancelled += requestCancelledHandler;
return removeHandlers;
}
private static void RemoveRequestHandlers(IRequestController controller, EventHandler<RequestControllerEventArgs<IRequestController>> requestFailedHandler, EventHandler<RequestControllerEventArgs<IRequestController>> requestCancelledHandler)
{
controller.RequestFailed -= requestFailedHandler;
controller.RequestCancelled -= requestCancelledHandler;
}
#endregion
#region IScoresController.LoadScores
private static TaskCompletionSource<Score[]> ScoresControllerLoadScoresAsyncSetup(IScoresController controller)
{
var tcs = new TaskCompletionSource<Score[]>();
EventHandler<RequestControllerEventArgs<IScoresController>> scoresLoadedHandler = null;
var removeHandlers = SetupRequestHandlers(controller, tcs, () => { controller.ScoresLoaded -= scoresLoadedHandler; });
scoresLoadedHandler = (s, e) =>
{
removeHandlers();
tcs.TrySetResult(controller.Scores);
};
controller.ScoresLoaded += scoresLoadedHandler;
return tcs;
}
public static Task<Score[]> LoadScoresAsync(this IScoresController @this, ScoreSearchList list, Range range, int mode = 0, ScoreloopGame game = null)
{
var tcs = ScoresControllerLoadScoresAsyncSetup(@this);
if (game == null)
game = @this.Game;
@this.LoadScores(list, range, mode, game);
return tcs.Task;
}
public static Task<Score[]> LoadScoresAsync(this IScoresController @this, ScoreSearchList list, Range range, Score scoreToInject, ScoreloopGame game = null)
{
var tcs = ScoresControllerLoadScoresAsyncSetup(@this);
if (game == null)
game = @this.Game;
@this.LoadScores(list, range, scoreToInject, game);
return tcs.Task;
}
public static Task<Score[]> LoadScoresAsync(this IScoresController @this, ScoreSearchList list, Score score, int limit, ScoreloopGame game = null)
{
var tcs = ScoresControllerLoadScoresAsyncSetup(@this);
if (game == null)
game = @this.Game;
@this.LoadScores(list, score, limit, game);
return tcs.Task;
}
public static Task<Score[]> LoadScoresAsync(this IScoresController @this, ScoreSearchList list, ulong rank, int limit, int mode = 0, ScoreloopGame game = null)
{
var tcs = ScoresControllerLoadScoresAsyncSetup(@this);
if (game == null)
game = @this.Game;
@this.LoadScores(list, rank, limit, mode, game);
return tcs.Task;
}
public static Task<Score[]> LoadScoresAsync(this IScoresController @this, ScoreSearchList list, User user, int limit, int mode = 0, ScoreloopGame game = null)
{
var tcs = ScoresControllerLoadScoresAsyncSetup(@this);
if (game == null)
game = @this.Game;
@this.LoadScores(list, user, limit, mode, game);
return tcs.Task;
}
#endregion
#region IScoreController.Submit
public static Task SubmitAsync(this IScoreController @this, Score score)
{
var tcs = new TaskCompletionSource<object>();
EventHandler<RequestControllerEventArgs<IScoreController>> scoreSubmittedHandler = null;
var removeHandlers = SetupRequestHandlers(@this, tcs, () => { @this.ScoreSubmitted -= scoreSubmittedHandler; });
scoreSubmittedHandler = (s, e) =>
{
removeHandlers();
tcs.TrySetResult(null);
};
@this.ScoreSubmitted += scoreSubmittedHandler;
@this.Submit(score);
return tcs.Task;
}
#endregion
#region IUserController.Load
private static TaskCompletionSource<User> UserControllerLoadAsyncSetup(IUserController controller)
{
var tcs = new TaskCompletionSource<User>();
EventHandler<RequestControllerEventArgs<IUserController>> userLoadedHandler = null;
var removeHandlers = SetupRequestHandlers(controller, tcs, () => { controller.UserLoaded -= userLoadedHandler; });
userLoadedHandler = (s, e) =>
{
removeHandlers();
tcs.TrySetResult(controller.User);
};
controller.UserLoaded += userLoadedHandler;
return tcs;
}
public static Task<User> LoadAsync(this IUserController @this, UserLoadScope scope)
{
var tcs = UserControllerLoadAsyncSetup(@this);
@this.Load(scope);
return tcs.Task;
}
public static Task<User> LoadAsync(this IUserController @this, Activity activity, UserLoadScope scope)
{
var tcs = UserControllerLoadAsyncSetup(@this);
@this.Load(activity, scope);
return tcs.Task;
}
public static Task<User> LoadAsync(this IUserController @this, User user, UserLoadScope scope)
{
var tcs = UserControllerLoadAsyncSetup(@this);
@this.Load(user, scope);
return tcs.Task;
}
#endregion
#region IUserController.Update
private static TaskCompletionSource<object> UserControllerUpdateAsyncSetup(IUserController controller)
{
var tcs = new TaskCompletionSource<object>();
EventHandler<RequestControllerEventArgs<IUserController>> userUpdatedHandler = null;
var removeHandlers = SetupRequestHandlers(controller, tcs, () => { controller.UserUpdated -= userUpdatedHandler; });
userUpdatedHandler = (s, e) =>
{
removeHandlers();
tcs.TrySetResult(null);
};
controller.UserUpdated += userUpdatedHandler;
return tcs;
}
public static Task UpdateAsync(this IUserController @this, string login, string email)
{
var tcs = UserControllerUpdateAsyncSetup(@this);
@this.Update(login, email);
return tcs.Task;
}
public static Task UpdateAsync(this IUserController @this, Context context)
{
var tcs = UserControllerUpdateAsyncSetup(@this);
@this.Update(context);
return tcs.Task;
}
public static Task UpdateAsync(this IUserController @this, DateTime birthDate)
{
var tcs = UserControllerUpdateAsyncSetup(@this);
@this.Update(birthDate);
return tcs.Task;
}
public static Task UpdateAsync(this IUserController @this, string nationality)
{
var tcs = UserControllerUpdateAsyncSetup(@this);
@this.Update(nationality);
return tcs.Task;
}
public static Task UpdateAsync(this IUserController @this, User user, Context context)
{
var tcs = UserControllerUpdateAsyncSetup(@this);
@this.Update(user, context);
return tcs.Task;
}
public static Task UpdateAsync(this IUserController @this, string login, string email, DateTime birthDate)
{
var tcs = UserControllerUpdateAsyncSetup(@this);
@this.Update(login, email, birthDate);
return tcs.Task;
}
public static Task UpdateAsync(this IUserController @this, string login, string email, string nationality, DateTime birthDate)
{
var tcs = UserControllerUpdateAsyncSetup(@this);
@this.Update(login, email, nationality, birthDate);
return tcs.Task;
}
#endregion
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment