Castle Windsor Wcf 自托管 InstanceContextMode.Single
Castle Windsor Wcf self host with InstanceContextMode.Single
所以,我在 windows 服务中实现了一个自托管的有状态 Wcf 服务。
我将此服务用作远程硬件驱动程序(有点)。
由于服务必须强制对底层硬件进行串行访问,因此我将服务设置为具有属性的唯一单个实例:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
它工作正常,但现在我想让 Castle 为我管理依赖项,麻烦就开始了。
我发现依赖注入和单实例模式不能很好地协同工作(here 是一个参考,但你可以找到更多的谷歌搜索)...
请注意,我不能使用 Castle 提供的标准单例,因为我需要为系统中安装的每个设备提供不同的实例(可以同时有多个)。所以使用 Castle 默认生命周期对我来说不是一个选项。
编辑
按照要求,我添加了我用来注册和解析服务的代码,虽然我觉得很标准,没有什么可下划线的。
这是我用来注册服务的代码:
container.Register(Component.For<IMyService>().ImplementedBy<MyService>().LifeStyle.Transient);
这是我用来解析服务的代码:
public ServiceHostBase Build<T>(SelfHostConfiguration configuration)
{
// Service configuration is done by code, not by App.config
Uri[] uris = configuration.Select(e => e.Uri).ToArray();
var serviceName = typeof(T).AssemblyQualifiedName;
DefaultServiceHostFactory factory = new DefaultServiceHostFactory();
var serviceHost = factory.CreateServiceHost(serviceName, uris);
return serviceHost;
}
没什么特别的,真的,但也许会有用。
问题:是否有人能够让 Castle 和 InstanceContextMode.Single 一起工作?有可能吗?
你能分享你的 solution/ideas 吗?
使用 WCF 工具时,您应该 remove the ServiceBehavior
attribute 并依靠 Windsor 来管理您的服务实例生命周期。如果将 InstanceContextMode
设置为 Single
,它将导致 WCF 使用自己的实例管理并有效地绕过 Windsor。
WCF 中的默认实例上下文模式将根据绑定(通常是 PerSession 或 PerCall)而有所不同,但在大多数情况下,它应该可以与您在 Windsor/WCF 设施注册时指定的任何生活方式一起正常工作。
更新
假设您要公开的每个设备的详细信息仅包含 'name' 和 'port' 并且可以在启动时发现这些详细信息,您可以注册并公开一个单例每个设备的服务如下:
var devices = GetDevices();
foreach (var device in devices)
{
container.Register(
Component.For<IMyService>()
.ImplementedBy<MyService>()
.Named("MyService:" + device.Name)
.LifestyleSingleton()
.DependsOn(Dependency.OnValue("devicePort", device.Port))
.AsWcfService(new DefaultServiceModel()
.AddEndpoints(
WcfEndpoint
.BoundTo(binding)
.At(new EndpointAddress("net.tcp://localhost/MyService/" + device.Name)))
));
}
所以,我在 windows 服务中实现了一个自托管的有状态 Wcf 服务。
我将此服务用作远程硬件驱动程序(有点)。
由于服务必须强制对底层硬件进行串行访问,因此我将服务设置为具有属性的唯一单个实例:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
它工作正常,但现在我想让 Castle 为我管理依赖项,麻烦就开始了。
我发现依赖注入和单实例模式不能很好地协同工作(here 是一个参考,但你可以找到更多的谷歌搜索)...
请注意,我不能使用 Castle 提供的标准单例,因为我需要为系统中安装的每个设备提供不同的实例(可以同时有多个)。所以使用 Castle 默认生命周期对我来说不是一个选项。
编辑
按照要求,我添加了我用来注册和解析服务的代码,虽然我觉得很标准,没有什么可下划线的。
这是我用来注册服务的代码:
container.Register(Component.For<IMyService>().ImplementedBy<MyService>().LifeStyle.Transient);
这是我用来解析服务的代码:
public ServiceHostBase Build<T>(SelfHostConfiguration configuration)
{
// Service configuration is done by code, not by App.config
Uri[] uris = configuration.Select(e => e.Uri).ToArray();
var serviceName = typeof(T).AssemblyQualifiedName;
DefaultServiceHostFactory factory = new DefaultServiceHostFactory();
var serviceHost = factory.CreateServiceHost(serviceName, uris);
return serviceHost;
}
没什么特别的,真的,但也许会有用。
问题:是否有人能够让 Castle 和 InstanceContextMode.Single 一起工作?有可能吗?
你能分享你的 solution/ideas 吗?
使用 WCF 工具时,您应该 remove the ServiceBehavior
attribute 并依靠 Windsor 来管理您的服务实例生命周期。如果将 InstanceContextMode
设置为 Single
,它将导致 WCF 使用自己的实例管理并有效地绕过 Windsor。
WCF 中的默认实例上下文模式将根据绑定(通常是 PerSession 或 PerCall)而有所不同,但在大多数情况下,它应该可以与您在 Windsor/WCF 设施注册时指定的任何生活方式一起正常工作。
更新
假设您要公开的每个设备的详细信息仅包含 'name' 和 'port' 并且可以在启动时发现这些详细信息,您可以注册并公开一个单例每个设备的服务如下:
var devices = GetDevices();
foreach (var device in devices)
{
container.Register(
Component.For<IMyService>()
.ImplementedBy<MyService>()
.Named("MyService:" + device.Name)
.LifestyleSingleton()
.DependsOn(Dependency.OnValue("devicePort", device.Port))
.AsWcfService(new DefaultServiceModel()
.AddEndpoints(
WcfEndpoint
.BoundTo(binding)
.At(new EndpointAddress("net.tcp://localhost/MyService/" + device.Name)))
));
}