Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unity DI on a Windows Service, Is possible?

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 :)

like image 307
juan25d Avatar asked Aug 05 '14 09:08

juan25d


People also ask

Can you use dependency injection in unity?

Scene-based dependency injection means you can setup up the Unity hierarchy and your MonoBehaviors however you like. It scans your scene and automatically wires together your MonoBehaviors. It allows you to connect objects in the Unity hierarchy without having to manually use functions such as FindObjectOfType(...) .

What is use of Microsoft practices unity?

Unity is one among the Microsoft Application Blocks. It is basically introduced as an IOC container by Microsoft, which helps in easy object creation and de-coupling the module dependencies in your project. To use it, just add the reference of the Unity DLLs to your project.

Is Microsoft unity deprecated?

This package has been deprecated as it is legacy and is no longer maintained. Due to a complete lack of interest from the community to support this project, it has been archived and will no longer be maintained.


1 Answers

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 (var scope = this.container.BeginLifetimeScope())
        {
            var service = scope.Resolve<IEventCheckerService>();

            service.Process();
        }
    }
}
like image 72
Steven Avatar answered Sep 19 '22 09:09

Steven