简体   繁体   中英

Using Castle windsor to resolve WCF service usingfactorymethod

I'm trying to see if this is possible. I want to resolve the WCF service class from castle windsor via a factory class. The WCF service is hosted in IIS and so far I've only been getting a 404 when I try to call the service when using the factory. Here is my registration code:

container.AddFacility<WcfFacility>();

container.Register(Component.For<IServiceFactory>() 
                            .ImplementedBy<ServiceFactory>()
                            .LifestyleSingleton());

container.Register(Component.For<IFooService>()
                            .UsingFactoryMethod((kernel, context)
                                    => kernel.Resolve<IServiceFactory>()
                                                     .CreateService(context.RequestedType))                                     
                            .Named("FooService")
                            .LifestylePerWcfOperation());

Here is my factory class:

public class ServiceFactory : IServiceFactory
{
    public IFooService CreateService(Type forType)
    {
        IFooService createdType = null;

        if (forType == typeof(IFooService))
            createdType = new FooService();

        return createdType;
    }
}

I have tried doing a strait .ImplementedBy<FooService>() and that works fine. It's only when I want to do it via a factory that I have a problem. Is this possible, meaning I'm missing something, or is it not possible?

(I know that the code shown is pretty simple, I am only testing if its possible before fully implementing my factory code)

you don't have to create a custom ServiceHost to do this, though you're right this is harder than it should be. The article that eouw0o83hf references first talks about an IInstanceProvider. That's the key, but you can wire it up using and WCF ServiceBehavior as well instead of a customer ServiceHost. I'm not sure what your FactoryMethod has to do with this - it sounds like it's a general wire up issue... or I'm not understanding your problem. I'll show below how I do the wire up without the ServiceHost and hopefully that fixes your problem.

First create a class that implements IInstanceProvider - mine below calls out to my ObjectResolver class with wraps Windsor. I'll leave that out for brevity.

using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;

public class ObjectResolverInstanceProvider : IInstanceProvider
{
    private readonly Type _serviceType;

    public ObjectResolverInstanceProvider(Type serviceType)
    {
        _serviceType = serviceType;
    }

    public object GetInstance(InstanceContext instanceContext)
    {
        return ObjectResolver.Resolve(_serviceType);
    }

    public object GetInstance(InstanceContext instanceContext, Message message)
    {
        return ObjectResolver.Resolve(_serviceType);
    }

    public void ReleaseInstance(InstanceContext instanceContext, object instance)
    {
        ObjectResolver.Release(instance);
    }
}

Then create a service behavior that assigns your instance provider to each endpoint's DispatchRuntime's InstanceProvider:

using System;
using System.Collections.ObjectModel;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;

public class ConstructWithObjectResolverAttribute : Attribute, IServiceBehavior
{
    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers)
        {
            ChannelDispatcher cd = cdb as ChannelDispatcher;

            if (cd != null)
            {
                foreach (EndpointDispatcher ed in cd.Endpoints)
                {
                    ed.DispatchRuntime.InstanceProvider = new ObjectResolverInstanceProvider(serviceDescription.ServiceType);
                }
            }
        }
    }

    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
    {
    }

    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
    }
}

Next apply the service attribute to your service implementation... note you could do this in config if you wanted too, but I prefer applying it via an attribute like so:

   [ConstructWithObjectResolver]
   [ServiceBehavior(Namespace="YourNamespace")]
   public class FooService : IFooService {}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM