Search code examples
c#wcfcastle-windsor

Register different settings for IServiceBehavior using CastleWindsor


I've a project with several WCF services inside of a .dll. Project uses Castle Windsor. There is also an SecurityServiceBehavior implements IServiceBehavior that WCF services should use. The SecurityServiceBehavior constructor needs the ISecuritySettingsProvider passed as argument. How it works without Windsor:

public class Service1Factory : ServiceHostFactory
{
    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
    {
        var host = base.CreateServiceHost(serviceType, baseAddresses);
        ISettingsProvider settingsProvider = new Service1SettingsProvider();
        host.Description.Behaviors.Add(new SecurityServiceBehavior(settingsProvider));
        return host;
    }
}
public class Service2Factory : ServiceHostFactory
{
    //the same but uses Service2SettingsProvider instead of Service1SettingsProvider

Then I can use this factories in .svc file. Now, how I'm registering this using Windsor:

Container.AddFacility<WcfFacility>();
Container.RegisterTransient<IServiceBehavior, SecurityServiceBehavior>();
Container.Register(Component.For<IService1>().
    ImplementedBy<Service1>().LifeStyle.PerWcfSession());
Container.Register(Component.For<IService2>().
    ImplementedBy<Service2>().LifeStyle.PerWcfSession());
//Need somehow fix this lines:
Container.Register(Component.For<ISecuritySettingsProvider>()
    .ImplementedBy<Service1SettingsProvider>().LifestyleSingleton());
Container.Register(Component.For<ISecuritySettingsProvider>()
    .ImplementedBy<Service2SettingsProvider>().LifestyleSingleton());

But it won't work the way I need cos I need SecurityServiceBehavior Service1SettingsProvider for Service1 and Service2SettingsProvider for Service2. What is the best way to do that?


Solution

  • Since there is no answer, I'll post solution I've finally used. Probably it could be also done via SubResolvers, but I haven't found a way to understand which service settings should belongs to. Instead of that, I've changed Service1Factory to derive Windsor's DefaultServiceHostFactory like this:

    public class Service1Factory : DefaultServiceHostFactory
    {
        public Service1Factory()
            : base(Service1Factory.CreateKernel())
        {
        }
    
        private static IKernel CreateKernel()
        {
            var Container = AppContext.Container; // application container
            var serviceContainer = new WindsorContainer();
            serviceContainer.AddFacility<WcfFacility>();
            serviceContainer.Register(Component.For<IService1>().ImplementedBy<Service1>().LifestyleTransient());
            serviceContainer.Register(Component.For<IServiceBehavior>().ImplementedBy<SecurityServiceBehavior>().LifestyleTransient());
            serviceContainer.Register(Component.For<ISecuritySettingsProvider>()
                .ImplementedBy<Service1SettingsProvider>().LifestyleSingleton());
            Container.AddChildContainer(serviceContainer);
            return serviceContainer.Kernel;
        }
    }
    

    By deriving DefaultServiceHostFactory and using CreateKernel() method I've provided Service1 it's unique container that Windsor also used to resolve IServiceBehavior. But I need app Container as well, so I've used Windsor's child container. Service2Factory is declared similar but uses Service2 and Service2SettingsProvider.