用于多个端点的Windsor WCF客户端

本文关键字:Windsor WCF 客户端 端点 用于 | 更新日期: 2023-09-27 18:15:22

我有一个服务运行在多个配置非常相似的不同服务器上。我希望能够使用Castle Windsor WCF Facility为任意端点地址生成客户端。

public class ServiceFactory {
    public IService GetService(string hostName){
        ....
    }
}

现在,我将在编译时知道我所有的服务将是什么,所以我可以这样做:

var container = new WindsorContainer();
// ...
container.AddFacility<WcfFacility>(f => f.CloseTimeout = TimeSpan.Zero);
container.Register(Component.For<IService>().AsWcfClient(new DefaultClientModel()
{
    Endpoint = WcfEndpoint.BoundTo(new NetTcpBinding()).At("net.tcp://hostname:port")
}).Named("hostname"));

然后像这样设置我的ServiceFactory:

public class ServiceFactory
{
    private readonly IWindsorContainer _container;
    public ServiceFactory(IWindsorContainer container)
    {
        _container = container;
    }
    public IService GetService(string hostName)
    {
        return _container.Resolve<IService>(hostName);
    }
}

但是对于我忘记配置一个特定的端点来说,这并不健壮。有没有更优雅的解决方案?

用于多个端点的Windsor WCF客户端

我不得不通过WCF设施的源代码,但是的!有一个更优雅的解决方案:

WCF工具与类型化工厂工具集成,后者用于在运行时动态创建工厂。WCF工具向类型化工厂工具添加功能,用于解析从IWcfEndpoint生成服务连接的工厂。

具体来说,它知道如何解析工厂方法的形式:

IService Create(IWcfEndpoint endpoint);

其中IService是具有[ServiceContract]属性的东西。

首先,我让我的服务工厂依赖于一个Func<IWcfEndpoint,IService>:

public class ServiceFactory {
    public ServiceFactory(Func<IWcfEndpoint, IService> resolveService){
        _resolveService = resolveService;
    }
    public IService GetService(string hostName){
        return _resolveService(WcfEndpoint.BoundTo(new NetTcpBinding()).At($"net.tcp://{hostName}:port"));
    }
}

然后在安装时,我添加了TypedFactoryFacility:

var container = new WindsorContainer();
// ...
container.AddFacility<TypedFactoryFacility>();
container.AddFacility<WcfFacility>(f => f.CloseTimeout = TimeSpan.Zero);
container.Register(
    Component.For<Func<IWcfEndpoint, IService>>().AsFactory(),
    Component.For<ServiceFactory>().ImplementedBy<ServiceFactory>());   

Windsor将为任何请求ServiceFactory的对象提供一个ServiceFactory,并将其连接起来,从主机名生成一个IService客户端:

public class FooClass {
    public FooClass(ServiceFactory serviceFactory){
        var service = serviceFactory.GetService("localhost");
    }
}