HubConnection
s およびs (ハブ メソッド呼び出しにバインドできるようにする) または下位レベルの APIに関する質問への回答があるかもしれませんが、IHubProxy
これについて間違った方法で行っている可能性があると思います。
概念的には、 でGeoFeedHub
クライアント リクエストを処理し、TwitterStream
クラスで Twitter API との対話を処理する必要があります。したがって、GeoFeedHub
クラスは に依存していTwitterStream
ます。
TwitterStream
クラスにasync
メソッドがあるのは良いことであり、これはSignalR で完全にサポートされています。を呼び出す非同期ハブ メソッドを使用できるため、で使用TwitterStream
する必要がなくなります。 TaskFactory
Global.asax
アプリケーションの開始時に作成してTwitterStream
Hub 呼び出しをそれにバインドする方法を見つけようとする (後方依存性と単一責任原則の違反) 代わりに、リアルタイム クライアント間の接点として Hub を立てる方がクリーンです。のインスタンスを にTwitterStream
挿入しGeoFeedHub
て、Hub が Twitter API にアクセスできるようにします。
このアイデアを説明するためのサンプル コードを次に示します。
public class GeoFeedHub : Hub
{
// Declare dependency on TwitterStream class
private readonly TwitterStream _twitterStream;
// Use constructor injection to get an instance of TwitterStream
public GeoFeedHub(TwitterStream _twitterStream)
{
_twitterStream = _twitterStream;
}
// Clients can call this method, which uses the instance of TwitterStream
public async Task SetStreamBounds(double latitude, double longitude)
{
await _twitterStream.SetStreamBoundsAsync(latitude, longitude);
}
}
public class TwitterStream
{
public TwitterStream()
{
}
public async Task SetStreamBoundsAsync(double latitude, double longitude)
{
// Do something with Twitter here maybe?
await SomeComponent.SetStreamBoundsAsync(latitude, longitude);
}
// More awesome code here
}
この例では DI を使用しているので、これを接続するために必要なグルー コードの一部を次に示します。このコードはあなたのApp_Start
フォルダに入ります:
// Configure Unity as our DI container
public class UnityConfig
{
private static readonly Lazy<IUnityContainer> Container = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
public static IUnityContainer GetConfiguredContainer()
{
return Container.Value;
}
private static void RegisterTypes(IUnityContainer container)
{
var twitterService = new TwitterService();
container.RegisterInstance(twitterService);
/*
* Using RegisterInstance effectively makes a Singleton instance of
* the object accessible throughout the application. If you don't need
* (or want) the class to be shared among all clients, then use
* container.RegisterType<TwitterService, TwitterService>();
* which will create a new instance for each client (i.e. each time a Hub
* is created, you'll get a brand new TwitterService object)
*/
}
}
// If you're using ASP.NET, this can be used to set the DependencyResolver for SignalR
// so it uses your configured container
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(UnitySignalRActivator), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethod(typeof(UnitySignalRActivator), "Shutdown")]
public static class UnitySignalRActivator
{
public static void Start()
{
var container = UnityConfig.GetConfiguredContainer();
GlobalHost.DependencyResolver = new SignalRUnityDependencyResolver(container);
}
public static void Shutdown()
{
var container = UnityConfig.GetConfiguredContainer();
container.Dispose();
}
}
public class SignalRUnityDependencyResolver : DefaultDependencyResolver
{
private readonly IUnityContainer _container;
public SignalRUnityDependencyResolver(IUnityContainer container)
{
_container = container;
}
public override object GetService(Type serviceType)
{
return _container.IsRegistered(serviceType)
? _container.Resolve(serviceType)
: base.GetService(serviceType);
}
public override IEnumerable<object> GetServices(Type serviceType)
{
return _container.IsRegistered(serviceType)
? _container.ResolveAll(serviceType)
: base.GetServices(serviceType);
}
}