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)))
            ));
}