可以使用Windows服务上的Unity DI吗?

jua*_*25d 12 c# windows-services dependency-injection unity-container

我正在开发一个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);
    }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,EventBL始终为null,因此不能通过统一的[Dependency]来解决.有没有办法使它工作?

谢谢!


解决方案:

写完答案后我发现了一个可能的解决方案,调用构建容器的方法来创建服务类的工作原理:

    UnityContainer container = new UnityContainer();
    UnityConfig.RegisterComponents(container);

    ServiceBase[] ServicesToRun;
    ServicesToRun = new ServiceBase[] 
    { 
        container.BuildUp(new EventChecker())
    };
    ServiceBase.Run(ServicesToRun);
Run Code Online (Sandbox Code Playgroud)

如果你知道任何其他解决方案,请分享:)

Ste*_*ven 21

当然,您可以使用DI库来帮助您使用Windows服务.请注意,通常您应该更喜欢使用构造函数注入.这可以防止时间耦合,并防止您的代码依赖于DI库本身(这非常具有讽刺意味,需要依赖于DI库,因为它试图帮助您防止组件之间的强耦合).

此外,您应该让容器解析您的服务.换句话说,不要手动新增服务,而是从容器中请求新实例:

ServicesToRun = new ServiceBase[] 
{ 
    container.Resolve<EventChecker>()
};
Run Code Online (Sandbox Code Playgroud)

但请注意,您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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @mithun:一个DI库,它不允许您通过将服务注入其他服务来自动为您构建相关对象的图形,这是完全没用的.在这种情况下,您可以更好地使用[Pure DI](http://blog.ploeh.dk/2014/06/10/pure-di/).大多数DI库可以为您构建完整的图形. (2认同)