Using Unity Dependency Injection with WCF services

非 Y 不嫁゛ 提交于 2019-11-28 23:33:25

ServiceHostFactory is for hosting in IIS. In self hosting you should use your derived ServiceHost directly. Here you have whole example including Unity configuration.

I´m using the following classes in my windows service to create WCF services and inject dependencies to it using unity.

UnityInstanceProvider:

internal class UnityInstanceProvider : IInstanceProvider {

    private readonly IUnityContainer container;
    private readonly Type contractType;

    public UnityInstanceProvider(IUnityContainer container, Type contractType) {
        this.container = container;
        this.contractType = contractType;
    }

    public object GetInstance(InstanceContext instanceContext) {
        return GetInstance(instanceContext, null);
    }

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

    public void ReleaseInstance(InstanceContext instanceContext, object instance) {
        container.Teardown(instance);
    }
}

UnityServiceBehavior:

public class UnityServiceBehavior : IServiceBehavior {

    private readonly IUnityContainer container;

    public UnityServiceBehavior(IUnityContainer container) {
        this.container = container;
    }

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

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

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) {
        foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers) {
            foreach (EndpointDispatcher endpointDispatcher in channelDispatcher.Endpoints) {
                if (endpointDispatcher.ContractName != "IMetadataExchange") {
                    string contractName = endpointDispatcher.ContractName;
                    ServiceEndpoint serviceEndpoint = serviceDescription.Endpoints.FirstOrDefault(e => e.Contract.Name == contractName);
                    endpointDispatcher.DispatchRuntime.InstanceProvider = new UnityInstanceProvider(this.container, serviceEndpoint.Contract.ContractType);
                }
            }
        }
    }
}

UnityServiceHost:

public class UnityServiceHost : ServiceHost {

    private IUnityContainer unityContainer;

    public UnityServiceHost(IUnityContainer unityContainer, Type serviceType)
        : base(serviceType) {
        this.unityContainer = unityContainer;
    }

    protected override void OnOpening() {
        base.OnOpening();

        if (this.Description.Behaviors.Find<UnityServiceBehavior>() == null) {
            this.Description.Behaviors.Add(new UnityServiceBehavior(this.unityContainer));
        }
    }
}

With this classes you can do the following (The configuration of services is done in .config):

UnityContainer container = new UnityContainer();
UnityServiceHost serviceHost = new UnityServiceHost(container, typeof("Type of Service to host"));
serviceHost.Open();

The CreateServiceHost method expects an array of Uri instances, so try this instead:

ServiceHost host = shf.CreateServiceHost(serviceType, new[] { serviceUri });

You can map interfaces to types in either XML or code, but I'd recommend code, since XML has too high a maintenance overhead.

The Main method is an excellent Composition Root, but if you want to configure the container at that level, you'll need to pass it from the Main method to MyServiceHostFactory - which is perfectly fine when you host the service in a console application, but will not work if you want to host it in IIS, where MyServiceHostFactory should be the Composition Root, since IIS requires a default constructor.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!