2014-02-13 51 views
2

我的應用程序使用「SignalR」客戶端/服務器通信框架。如果您不熟悉它,服務器端應用程序通常包含一個或多個「集線器」類(類似於asmx Web服務),每個類提供可由客戶端調用的方法。在啓動過程中,客戶端需要先建立一個連接,然後創建每個輪轂,這將需要傾訴,例如「代理」: -溫莎城堡 - 如何解決名稱?

var hubConnection = new HubConnection("http://..."); 
var fooHubProxy = hubConnection.CreateHubProxy("FooHub"); 
var barHubProxy = hubConnection.CreateHubProxy("BarHub"); 
...etc... 

傳遞給CreateHubProxy()的字符串參數的名稱服務器端集線器類。方法返回類型是IHubProxy

感覺就像我應該能夠在這裏使用溫莎一樣,但我正在努力尋找解決方案。我的第一個想法是實例化集線器代理並將這些實例註冊到Windsor(通過名稱),例如,

var fooHubProxy = hubConnection.CreateHubProxy("FooHub"); 
container.Register(Component.For<IHubProxy>().Instance(fooHubProxy).LifestyleSingleton().Named("FooHub")); 
...etc... 

的問題是,當一個類需要一箇中心代理,只有這樣,才能解決它的名字是使用服務定位器模式,這是不推薦使用。溫莎的其他功能(例如打字工廠等)在這裏可能有用嗎?

編輯

我只是發現溫莎.UsingFactoryMethod,並且想知道這是否會工作,以簡化集線器註冊:

container.Register(Component.For<IHubProxy>() 
        .UsingFactoryMethod((kernel, context) => hubConnection.CreateHubProxy("FooHub")) 
        .LifestyleSingleton() 
        .Named("FooHub")); 

我想我仍然對如何解決問題儘管如此。

回答

2

好吧,我想我已經找到了一個可能的解決方案,部分使用方法詳細here這說明它是如何可能的溫莎註冊Func<>秒。

首先,我註冊了一個使用集裝箱通過名稱來解決委託(Func鍵<>): -

Container.Register(Component.For<Func<string, IHubProxy>>() 
        .Instance(name => Container.Resolve<IHubProxy>(name)) 
        .LifestyleSingleton()); 

認爲這是一個IHubProxy 「工廠」。

接着,註冊我轂代理詳見我原來的問題: -

container.Register(Component.For<IHubProxy>() 
       .UsingFactoryMethod((kernel, context) => hubConnection.CreateHubProxy("FooHub")) 
       .LifestyleSingleton() 
       .Named("FooHub")); 
container.Register(Component.For<IHubProxy>() 
       .UsingFactoryMethod((kernel, context) => hubConnection.CreateHubProxy("BarHub")) 
       .LifestyleSingleton() 
       .Named("BarHub")); 

這裏是需要在輪轂代理的實例的類的例子: -

public class SomeClass 
{ 
    private IHubProxy _fooHub; 
    private IHubProxy _barHub; 

    public SomeClass(Func<string, IHubProxy> hubProxyFactory) 
    { 
     _fooHub = hubProxyFactory("FooHub"); 
     _barHub = hubProxyFactory("BarHub"); 
    } 
} 

未經審訊到目前爲止,但它看起來很有希望。這是一個聰明的解決方案,但注入Func <>感覺有點冒險,所以我仍然渴望聽到其他可能的解決方案來解決我的問題。

1

我剛剛使用了類似的方法給你。我使用一個打字的工廠。好處是我有我的集線器類型安全。註冊集線器是一樣的。其餘的有點不同,但技術上是一樣的。

IServiceFactory { 
    IHubProxy GetFooHub(); 
    IHubProxy GetBarHub(); 
} 

和登記:

Container.AddFacility<TypedFactoryFacility>(); 
Container.Register(Component.For<IServiceFactory>().AsFactory()); 

用法:

public class SomeClass 
{ 
    private IHubProxy _fooHub; 
    private IHubProxy _barHub; 

    public SomeClass(IServiceFactry hubProxyFactory) 
    { 
     _fooHub = hubProxyFactory.GetFooHub(); 
     _barHub = hubProxyFactory.GetBarHub(); 
    } 
} 

順便說一句。 Factory.Get"Name"()按名稱解析。

4

兩年後,但我對其他人也遇到了更爲優雅的解決方案,這些問題也可以解決這個問題。 它可以使用TypedFactory設施和你需要像here適應它。 首先創建工廠接口(!只是不需要在實際執行中,城堡會照顧那個):

public interface IHubProxyFactory 
{ 
    IHubProxy GetProxy(string proxyName); 
} 

現在我們需要的是擴展默認輸入facotory從輸入retreives組件的名稱類(proxyName):

class NamedTypeFactory : DefaultTypedFactoryComponentSelector 
{ 
    protected override string GetComponentName(MethodInfo method, object[] arguments) 
    { 
     string componentName = null; 
     if (arguments!= null && arguments.Length > 0) 
     { 
      componentName = arguments[0] as string; 
     } 

     if (string.IsNullOrEmpty(componentName)) 
      componentName = base.GetComponentName(method, arguments); 

     return componentName; 
    } 
} 

,然後註冊工廠的城堡,並指定你的NamedTypeFactory將用於:

Component.For<IHubProxyFactory>().AsFactory(new NamedTypeFactory()) 

現在每個類都可以得到工廠接口的構造函數中:

public class SomeClass 
{ 
    private IHubProxy _fooHub; 
    private IHubProxy _barHub; 

    public SomeClass(IHubProxyFactory hubProxyFactory) 
    { 
     _fooHub = hubProxyFactory.GetProxy("FooHub"); 
     _barHub = hubProxyFactory.GetProxy("BarHub"); 
    } 
}