Unity DI on a Windows Service, Is possible?

juan25d picture juan25d · Aug 5, 2014 · Viewed 14.5k times · Source

I am developing a Windows Service to do some periodical operations, can I use Unity to inject my classes from another library there?

I want to use with the [Dependency] attribute on my services, registering the components on the entry point of the windows service start.

Example:

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);
    }
}

In this scenario the EventBL is always null, so is not resolved by the [Dependency] of unity. There aren't a way to make it working?

Thanks!


Solution Found:

After write the answer I found a possible solution, calling to build up method of the container to create the service class works:

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

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

If you know any other solution, please share it :)

Answer

Steven picture Steven · Aug 5, 2014

A DI Container like Unity can just as well be used to compose the object graphs of Windows Services. Note that in general you should prefer using constructor injection. This prevents temporal coupling and prevents your code to have a dependency on the DI library itself (which is quite ironic to have need dependency on the DI library, since it's trying to help you preventing strong coupling between components).

Furthermore, you should simply let the container resolve your services. In other words, don't new up your services by hand, but request a new instance from the container:

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

But do note that your EventChecker is resolved once and stored for the duration of the application. That effectively makes it a singleton and with that all its dependencies will becomes singletons. So instead, it's better to make your ServiceBase implementation part of the composition root and resolve new instances from the container every time your time fires:

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();
        }
    }
}