2014-07-21 2 views
0

의 클라이언트에서 허브 클래스의 외부에있는 서버 메소드를 호출 수업? 서버 (및 Hub 클래스 외부)에서 클라이언트 함수를 호출 할 수도 있지만 다른 방법으로 수행 할 수 있습니까?아래의 클래스 고려 SignalR

불행히도 필자는 약간의 코너로 돌아 왔고 코드는 필자가 작성한 클래스에서 실행해야합니다 (허브 자체가 아니라 SignalR 허브를 작업 공장으로 실행할 수있는 경우가 아니라면)

+0

왜 거기에서'TwitterStream'의 인스턴스에 다음 전화'ChangeStreamBounds'를 클라이언트에 의해 호출되는 GeoFeedHub''에 방법을 넣어 수 있습니까? –

+0

@RyanErdmann'Global.asax' /'Application_Start'에서'Task.Factory.StartNew (() => new TwitterStream());을 사용하여'TwitterStream' 클래스의 인스턴스를 만들고 있습니다. – adaam

+0

흥미 롭습니다. 'TwitterStream'의 목적은 무엇입니까? 'TwitterStream'은 본질적으로 애플리케이션을위한 싱글 톤 인스턴스입니다. –

답변

2

HubConnectionIHubProxy (허브 메서드 호출에 바인딩 할 수 있음)이나 낮은 수준의 API가 포함되어있을 수 있지만 사용자가 잘못 생각한 것 같습니다.

개념적으로 GeoFeedHub은 클라이언트 요청을 처리하고 TwitterStream 클래스는 Twitter API와 상호 작용을 처리해야합니다. 따라서 GeoFeedHub 클래스는 TwitterStream에 종속됩니다.

귀하의 TwitterStream 클래스에는 async 개의 메소드가 있으며이 값은 fully supported in SignalR입니다. TwitterStream을 호출하는 비동기 허브 메서드를 사용할 수 있으므로 TaskFactory 사용을 Global.asax에서 제거 할 필요가 없습니다.

응용 프로그램 시작시 TwitterStream을 만들고 허브 호출을 바인딩하는 방법을 찾는 대신 (뒤로 의존성 및 단일 책임 원칙 위반) 허브를 스탠드 포인트로 삼는 것이 더 깔끔합니다 귀하의 실시간 클라이언트 들간의 접촉, TwitterStream의 인스턴스를 GeoFeedHub에 삽입하여 허브가 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); 
    } 
} 
+0

고마워요! 좋은 대답 – adaam