我正在开发一个Windows服务来进行一些定期操作,我可以使用Unity从其他库中注入我的类吗?
我想在我的服务上使用[Dependency]属性,在windows服务启动的入口点注册组件。
示例:
static class Program
{
static void Main()
{
ServiceBase[] ServicesToRun;
UnityConfig.RegisterComponents();
ServicesToRun = new ServiceBase[]
{
new EventChecker()
};
ServiceBase.Run(ServicesToRun);
}
}
public static class UnityConfig
{
public static void RegisterComponents()
{
UnityContainer container = new UnityContainer();
container.RegisterType<IEventBL, EventBL>();
}
}
public partial class EventChecker : ServiceBase
{
private Logger LOG = LogManager.GetCurrentClassLogger();
[Dependency]
public Lazy<IEventBL> EventBL { get; set; }
protected override void OnStart(string[] args)
{
var events = EventBL.Value.PendingExecution(1);
}
}
在这种情况下,EventBL始终为null,因此不能通过统一的[Dependency]来解决。还没有办法让它发挥作用吗?
谢谢!
写完答案后我找到了一个可能的解决方案,调用构建容器的方法来创建服务类的工作原理:
UnityContainer container = new UnityContainer();
UnityConfig.RegisterComponents(container);
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
container.BuildUp(new EventChecker())
};
ServiceBase.Run(ServicesToRun);
如果您知道任何其他解决方案,请分享:)
答案 0 :(得分:20)
当然,您可以使用DI库来帮助您使用Windows服务。请注意,通常您应该更喜欢使用构造函数注入。这可以防止temporal coupling并阻止您的代码依赖于DI库本身(这非常具有讽刺意味,因为它需要依赖于DI库,因为它试图帮助您防止组件之间的强耦合)
此外,您应该让容器解析您的服务。换句话说,不要手动新增服务,而是从容器中请求新实例:
ServicesToRun = new ServiceBase[]
{
container.Resolve<EventChecker>()
};
但请注意,您的EventChecker
已解决一次,并在申请期间存储。这有效地使它成为一个单身人,并且所有它的依赖都将成为单身人士。因此,最好让你的ServiceBase
实现成为组合根的一部分,并在每次激活时从容器中解析新实例:
public class EventChecker : ServiceBase
{
private static IUnityContainer container;
public EventChecker(IUnityContainer container) {
this.container = container;
}
public void SomeOperationThatGetsTriggeredByATimer() {
using (this.container.StartSomeScope()) {
var service = this.container.Resolve<IEventCheckerService>();
service.Process();
}
}
}