DI与Windows服务中的Castle Windsor托管WCF服务
问题描述:
我想让Castle Windsor DI与作为Windows服务托管的WCF服务一起工作。我已经对这里的方法DI与Windows服务中的Castle Windsor托管WCF服务
WCF Service Library hosted as a Windows Service using Castle.Windsor 3.0 issue
不过,我的问题是,如果我的服务实现类不具有默认参数的构造函数,ServiceHost的不会让我在OnStart中创建的这个实例()。如果我提供一个无参数的构造函数,服务控制台将使用该构造函数启动服务,所以我没有注入任何依赖项。
代码如下
public class WindowsService : ServiceBase
{
public ServiceHost ServiceHost;
public WindowsService()
{
ServiceName = "CRMCustomerService";
}
public static void Main()
{
// Bootstrap the Castle Windsor DI setup
Run(CreateContainer().Resolve<ServiceBase>());
}
#region Service methods
protected override void OnStart(string[] args)
{
if (ServiceHost != null)
{
ServiceHost.Close();
}
ServiceHost = new ServiceHost(typeof(CustomerService));
ServiceHost.Open();
}
protected override void OnStop()
{
if (ServiceHost != null)
{
ServiceHost.Close();
ServiceHost = null;
}
}
#endregion
#region Private Methods
private static IWindsorContainer CreateContainer()
{
var container = new WindsorContainer();
container.Install(FromAssembly.This());
return container;
}
#endregion
}
[ServiceBehaviorAttribute(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Single)]
public class CustomerService : ICustomerService
{
private readonly IDataRepository _repository;
private readonly ILogger _logger;
public CustomerService(IDataRepository repository)
{
_repository = repository;
_logger = new RootLogger(Level.Error);
}
}
public class ServicesInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container
.AddFacility<WcfFacility>(f =>
{
f.CloseTimeout = TimeSpan.Zero;
})
.Register(
Component
.For<IDataRepository>()
.ImplementedBy<CustomerRepository>()
.LifeStyle.Transient
.AsWcfService(),
Component.For<ServiceBase>().ImplementedBy<WindowsService>());
}
}
有人能看到我在做什么错?我想在服务启动时以及WCF服务的一个实例创建时引导Windsors DI容器,以便在此时注入依赖关系。
答
你可以有两个构造函数。无参数的参数调用将依赖作为参数的重载。
public WindowsService()
this(new ServiceHost());
public WindowsService(ServiceHost serviceHost)
{
this.ServiceHost = serviceHost;
}
答
你可以实例化服务实现与所需的构造函数,并把它传递给服务主机作为参数,例如
var service = CustomerService(container.Resolve<IDataRepository>());
ServiceHost = new ServiceHost(service);
,甚至这样的,如果你已经正确配置容器:
var service = container.Resolve<ICustomerService>();
ServiceHost = new ServiceHost(service);
然而,在这种情况下,将在单模式下工作,我记得你需要改变InstanceContextMode的服务实施到单一。
答
1)您应该有两个构造函数作为另一个海报建议,一个 默认和一个与您的依赖关系作为参数。
2)当你在你连接到你应该使用城堡的WCF基金 主机服务(请注意您 链接到岗位AsWcfService
语法后见)。所有你需要做的就是编写城堡代码,注册 你所有的服务依赖关系,Castle将会照顾 休息。这几乎像魔术一样!