Reputation: 2958
So, I have implemented a stateful Wcf Service self-hosted inside a windows service.
I use this service as a remote hardware driver (kind of).
As the service has to force serialed access to the underlying hardware, I set the service as a unique single instance with the attribute:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
It works correctly but now i want to have Castle manage dependencies for me, and here troubles start.
I found out that dependency injection and Single Instance Mode do not work well together (here is a reference, but you can find many more googling)...
Please note that I cannot use standard singletons provided by Castle as I need a different instance for every device installed in the system (there can be multiple at the same time). So using Castle default lifetime is not an option for me.
EDIT
As requested, I added the code I use to register and resolve the service, even if I think it's quite standard and there is nothing to underline.
This is the code I use to register the service:
container.Register(Component.For<IMyService>().ImplementedBy<MyService>().LifeStyle.Transient);
And this is the code I use to resolve the service:
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;
}
Nothing special, really, still maybe it'll be useful.
The question: is there anybody that was able to make Castle and InstanceContextMode.Single work together? Is it even possible?
Can you share your solution/ideas?
Upvotes: 0
Views: 587
Reputation: 7264
When using the WCF Facility you should remove the ServiceBehavior
attribute and rely upon Windsor to manage your service instance lifecycle. If you set the InstanceContextMode
to Single
it will cause WCF to use its own instance management and effectively bypass Windsor.
The default instance context mode in WCF will vary depending on the binding (usually PerSession or PerCall) but in most cases it should work properly with whatever life style you specify when registering with Windsor/WCF Facility.
Assuming that the details about each device you want to expose consist only of 'name' and 'port' and that those details can be discovered at start-up time, you could register and expose a singleton service for each device as follows:
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)))
));
}
Upvotes: 1