我在 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服务?