Windows Service上实现Unity DI,是否可能?

16

我正在开发一个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始终为空,因此不会被unity的[Dependency]解析。有没有办法让它工作?
谢谢!
找到解决方案:
在写出答案后,我发现调用容器的build up方法来创建服务类可以起作用:
    UnityContainer container = new UnityContainer();
    UnityConfig.RegisterComponents(container);

    ServiceBase[] ServicesToRun;
    ServicesToRun = new ServiceBase[] 
    { 
        container.BuildUp(new EventChecker())
    };
    ServiceBase.Run(ServicesToRun);
如果您知道其他的解决方案,请分享它 :)

如果您知道其他的解决方案,请分享它 :)

1个回答

25

像Unity这样的DI容器同样可以用于组成Windows服务的对象图。请注意,通常情况下应优先使用构造函数注入。这可以防止时间耦合并防止您的代码对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 (var scope = this.container.BeginLifetimeScope())
        {
            var service = scope.Resolve<IEventCheckerService>();

            service.Process();
        }
    }
}

谢谢,这样更好。 - juan25d
1
这会自动解决EventCheckerService中的其他注入以及在那里注入的类中的注入吗? - mithun

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接