用于多个端点的 Windsor WCF 客户端
Windsor WCF Client for multiple endpoints
我在配置非常相似的多台不同服务器上有一项服务 运行。我希望能够使用 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);
}
}
但这对我忘记配置特定端点并不可靠。有没有更优雅的解决方案?
我不得不通过 WCF Facility 源代码进行探索,但是是的!有一个更优雅的解决方案:
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");
}
}
我在配置非常相似的多台不同服务器上有一项服务 运行。我希望能够使用 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);
}
}
但这对我忘记配置特定端点并不可靠。有没有更优雅的解决方案?
我不得不通过 WCF Facility 源代码进行探索,但是是的!有一个更优雅的解决方案:
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");
}
}