使用依赖注入的Windows服务托管WCF服务

时间:2014-07-02 08:06:30

标签: c# wcf dependency-injection windows-services castle-windsor

我在 Windows服务中托管 WCF服务,服务合约如下所示:

namespace ServiceLayer.WcfServiceLibrary.Contracts
{
    [ServiceContract]
    public interface IPersonnelManagementService
    {
        [OperationContract]
        Result CreatePerson(string sessionId, DTOs.Personnel.Person person);
    }
}

服务合同实施:

namespace ServiceLayer.WcfServiceLibrary
{
    public class PersonnelManagementService : IPersonnelManagementService
    {
        private PersonnelManager _personManager;
        private IPersonnelUnitOfWork _uowPersonnel;

        public ILogger Logger { get; set; }

        public PersonnelManagementService(IPersonnelUnitOfWork personnelUnitOfWork)
        {
            this._uowPersonnel= personnelUnitOfWork;
            this._personManager = new PersonnelManager(this._uowPersonnel);
        }

        public Result CreatePerson(string sessionId, DTOs.Personnel.Person person)
        {
            Some code goes here...
        }
    }
}

我使用Castle.Windsor通过从实例提供程序,服务行为和服务主机派生实例时需要为Web服务注入依赖项,如下所示:

实例提供商:

class DependencyResolverInstanceProvider : IInstanceProvider
{
    private readonly Type _serviceType;
    private readonly WindsorContainer _container;  

    public DependencyResolverInstanceProvider(Type serviceType)
    {
        this._container = new WindsorContainer();
        _container.Install(FromAssembly.Named("DependencyResolver"));

        _container.Register(Classes.FromThisAssembly());

        DTOs.DTOMapper.Initialize();
        this._serviceType = serviceType;
    }

    #region IInstanceProvider Members
    public object GetInstance(InstanceContext instanceContext)
    {
        return GetInstance(instanceContext, null);
    }

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

    public void ReleaseInstance(InstanceContext instanceContext, object instance)
    {
        if (instance is IDisposable)
            ((IDisposable)instance).Dispose();
    }
    #endregion
}

服务行为:

class DependencyResolverServiceBehavior:IServiceBehavior
{
    #region IServiceBehavior Members

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        serviceHostBase.ChannelDispatchers.ToList().ForEach(channelDispatcher =>
        {
            ChannelDispatcher dispatcher = channelDispatcher as ChannelDispatcher;

            if (dispatcher != null)
            {
                dispatcher.Endpoints.ToList().ForEach(endpoint =>
                {
                    endpoint.DispatchRuntime.InstanceProvider = new DependencyResolverInstanceProvider(serviceDescription.ServiceType);
                });
            }
        });
    }

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

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

    #endregion
}

服务主持人:

public class CustomServiceHost : ServiceHost
{
    public CustomServiceHost()
        : base()
    {

    }
    public CustomServiceHost(Type serviceType, params Uri[] baseAddresses)
        : base(serviceType, baseAddresses)
    {
    }

    protected override void OnOpening()
    {
        this.Description.Behaviors.Add(new DependencyResolverServiceBehavior());
        base.OnOpening();
    }
}

App.config文件配置为使用 net.tcp 协议,如下所示:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" />
  </system.web>
  <!-- When deploying the service library project, the content of the config file must be added to the host's 
  app.config file. System.Configuration does not support config files for libraries. -->
  <system.serviceModel>
    <services>
      <service behaviorConfiguration="netTcpBehavior" name="ServiceLayer.WcfServiceLibrary.PersonnelManagementService">
        <host>
          <baseAddresses>
            <add baseAddress="net.tcp://localhost:8523/PersonnelManagementService" />
          </baseAddresses>
        </host>
        <endpoint address="" binding="netTcpBinding" contract="ServiceLayer.WcfServiceLibrary.Contracts.IPersonnelManagementService" />
        <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="netTcpBehavior">
          <serviceMetadata httpGetEnabled="false" policyVersion="Policy15" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

我在同一个Windows服务中托管多个服务并使用相同的端口。我创建了一个Windows服务,将 App.config 内容复制到它。最后,我的Windows服务代码如下所示:

public partial class MainService : ServiceBase
{
    internal static ServiceHost _serviceHost = null;

    public MainService()
    {
        InitializeComponent();
    }

    protected override void OnStart(string[] args)
    {
        if (_serviceHost != null)
        {
            _serviceHost.Close();
        }

        _serviceHost = new CustomServiceHost(typeof(MainService));
        _serviceHost.Open();
    }

    protected override void OnStop()
    {
        if(_serviceHost!=null)
        {
            _serviceHost.Close();
            _serviceHost = null;
        }
    }
}

我的问题是:使用上面的代码,Windows主机服务无法初始化WCF服务。如果我将_serviceHost = new CustomServiceHost(typeof(MainService));更改为_serviceHost = new CustomServiceHost(typeof(PersonnelManagementService));它运行良好,但在这种情况下,即使 WCF服务主机总是向我显示错误,也只会运行一项服务:The service type provided could not be loaded as a service because it does not have a default (parameter-less) constructor

那么,如何配置我的服务以使用DI托管多个WCF服务?

0 个答案:

没有答案