Windows 服务上的 Unity DI,可能吗?

问题描述 投票:0回答:1

我正在开发一个 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,因此不会通过 unity 的 [Dependency] 来解决。有没有办法让它发挥作用?

谢谢!


找到解决方案:

写完答案后,我找到了一个可能的解决方案,调用容器的 build up 方法来创建服务类是可行的:

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

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

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

c# dependency-injection windows-services unity-container
1个回答
25
投票

像 Unity 这样的 DI 容器也可以用来构建 Windows 服务的对象图。请注意,通常您应该更喜欢使用构造函数注入。这可以防止“时间耦合”并防止您的代码依赖于 DI 库本身(这非常讽刺,需要依赖于 DI 库,因为它试图帮助您防止组件之间的强耦合)。 此外,您应该简单地让容器解析您的服务。换句话说,不要手动更新您的服务,而是从容器请求一个新实例:

ServicesToRun = new ServiceBase[] { container.Resolve<EventChecker>() };

但请注意,您的 
EventChecker

已解决一次并在应用程序期间存储。这实际上使它成为单例,并且它的所有依赖项都将成为单例。因此,最好将您的

ServiceBase
实现作为组合根的一部分,并在每次触发时从容器中解析新实例:
public class EventChecker : ServiceBase
{
    private readonly 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();
        }
    }
}

	
© www.soinside.com 2019 - 2024. All rights reserved.