Created
July 10, 2013 15:14
-
-
Save hanishi/5967154 to your computer and use it in GitHub Desktop.
SignalR HubConfigurator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.ComponentModel.Composition.Hosting; | |
using System.IO; | |
using System.Linq; | |
using System.Reflection; | |
using System.Threading.Tasks; | |
using Microsoft.AspNet.SignalR.Client.Hubs; | |
using System.ComponentModel.Composition; | |
namespace SignalR | |
{ | |
public class HubConfigurator : MarshalByRefObject, IDisposable | |
{ | |
private Sponsor<TextWriter> _log; | |
public TextWriter Log | |
{ | |
get { return (_log != null) ? _log.Instance : null; } | |
set { _log = (value != null) ? new Sponsor<TextWriter>(value) : null; } | |
} | |
[ImportMany(typeof (IHubClient))] | |
private IEnumerable<IHubClient> _clients; | |
private IEnumerable<Synchronizer> Synchronizer { get; set; } | |
internal HubConnectionSingleton HubConnection { get; set; } | |
public HubConfigurator() | |
{ | |
Log = TextWriter.Null; | |
HubConnection = HubConnectionSingleton.GetInstance(); | |
} | |
~HubConfigurator() | |
{ | |
Dispose(false); | |
} | |
private IEnumerable<Tuple<string, Synchronizer>> Configurations(IHubClient client) | |
{ | |
return from methodInfo in client.GetType().GetMethods() | |
let paramInfo = methodInfo.GetParameters() | |
where paramInfo.Length == 1 && paramInfo[0].ParameterType == typeof (IHubProxy) && methodInfo.ReturnType == typeof(void) | |
select Tuple.Create(methodInfo.Name, new Synchronizer(HubConnection.CreateHubProxy(methodInfo.Name))); | |
} | |
private IEnumerable<Synchronizer> Start() | |
{ | |
var sync = new List<Synchronizer>(); | |
foreach (var client in _clients) | |
{ | |
foreach (var configuration in Configurations(client)) | |
{ | |
var conf = configuration; | |
var c = client; | |
var method = c.GetType().GetMethod(conf.Item1); | |
var task = Task.Factory.StartNew(() => | |
{ | |
method.Invoke(c, new object[] {conf.Item2}); | |
}); | |
task.ContinueWith(_ => | |
{ | |
if (_.Exception != null) | |
{ | |
Console.WriteLine(_.Exception.InnerException.GetType().Name); | |
} | |
}, TaskContinuationOptions.OnlyOnFaulted); | |
sync.Add(conf.Item2); | |
} | |
} | |
return sync.ToArray(); | |
} | |
private async void SetUp() | |
{ | |
Synchronizer = Start(); | |
await HubConnection.Start(); | |
foreach (var sync in Synchronizer) | |
{ | |
sync.Resume(); | |
} | |
} | |
internal void SetUp(string directory) | |
{ | |
foreach (var dllFile in Directory.GetFiles(directory, "*.dll")) | |
{ | |
try | |
{ | |
var asm = Assembly.LoadFile(dllFile); | |
Console.WriteLine(dllFile); | |
Log.WriteLine("Loaded assembly {0} in {1}", asm.GetName().FullName, directory); | |
} | |
catch (ReflectionTypeLoadException rex) | |
{ | |
Console.WriteLine("{0} failed to load.", Path.GetFileName(dllFile)); | |
foreach (var ex in rex.LoaderExceptions) | |
{ | |
Log.WriteLine("\t{0}: {1}", ex.GetType().Name, ex.Message); | |
} | |
} | |
catch (BadImageFormatException e) | |
{ | |
Console.WriteLine("{0} is not a valid assembly.", Path.GetFileName(dllFile)); | |
} | |
catch (Exception ex) | |
{ | |
Console.WriteLine("{0} failed to load.", Path.GetFileName(dllFile)); | |
Console.WriteLine("\t{0}: {1}", ex.GetType().Name, ex.Message); | |
} | |
} | |
var catalog = new DirectoryCatalog(directory); | |
var container = new CompositionContainer(catalog); | |
container.SatisfyImportsOnce(this); | |
SetUp(); | |
} | |
private void TearDown() | |
{ | |
foreach (var sync in Synchronizer) | |
{ | |
Console.WriteLine("Stopped!"); | |
sync.Pause(); | |
sync.Stop(); | |
} | |
HubConnection.Stop(); | |
} | |
public void Dispose() | |
{ | |
Dispose(true); | |
GC.SuppressFinalize(this); | |
} | |
private void Dispose(bool disposing) | |
{ | |
if (!disposing) return; | |
TearDown(); | |
foreach (var hubClient in _clients) | |
{ | |
try | |
{ | |
hubClient.Dispose(); | |
} | |
catch (Exception ex) | |
{ | |
Log.WriteLine("{0} thrown while disposing {1}", ex.GetType(), hubClient); | |
Log.WriteLine("\t{0}: {1}", ex.GetType().Name, ex.Message); | |
} | |
} | |
if (_log != null) _log.Dispose(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment