简体   繁体   中英

how to use Simple Injector to Azure Worker Role

I referenced several documents but I need correct implementation to do it correctly.

References

  1. Unity to Worker Role: https://alexandrebrisebois.wordpress.com/2013/04/14/building-windows-azure-services-without-compromising-testability/

  2. SimpleInjector for Console app: http://simpleinjector.readthedocs.io/en/latest/consoleintegration.html

My questions

  1. Reference-1, Unity use using (var uc = new UnityContainer()){...} but SimpleInjector has ThreadScopedLifestyle or AsyncScopedLifestyle . Which one do I use?

  2. Reference-2 has static Main class, static readonly Container , and static contructor . Do I define static Container for Worker role? what about static constructor for dependency registration?

  3. I implemented as below My Implementation section. Is this code implemented correctly?

Reference Code

Reference 1;

static class Program
{
    static readonly Container container;

    static Program()
    {
        container = new Container();

        container.Register<IUserRepository, SqlUserRepository>();
        container.Register<MyRootType>();

        container.Verify();
    }

    static void Main()
    {
        var service = container.GetInstance<MyRootType>();
        service.DoSomething();
    }
}

Reference 2;

public class WorkerRole : RoleEntryPoint
{
 public override void Run()
 {
     // This is a sample worker implementation. Replace with your logic.
     Trace.WriteLine("Worker entry point called", "Information");

     using (var uc = new UnityContainer())
     {
         uc.RegisterType<ILogger, TableStorageLogger>();
         uc.RegisterType<IEnumerable<IMessageHandler>, IMessageHandler[]>();

         var processor = uc.Resolve<MessageProcessor>();

         while (true)
         {
             processor.Process();
             Thread.Sleep(10000);
             Trace.WriteLine("Working", "Information");
         }
     }
 }

My Implementation

I thought (1) Container could be enough to be static , (2) OnStart is good place to register services, and (3) I intended service instances are created and disposed per each loop.

public class WorkerRole : RoleEntryPoint
{
    static readonly Container container = new Container();

    public override void Run()
    {
        while (true)
        {
            using (ThreadScopedLifestyle.BeginScope(container))
            {
                var service = container.GetInstance<SomeService>();
                service.DoSomething();
            }
        }
    }

    public override bool OnStart(){
        // define.
        container.Register<SomeService>();
        container.Register<ProcessRecorderSetting>();
        container.Verify();
    } 
}

Note: I don't know above code is working.

Reference-1, Unity use using (var uc = new UnityContainer()){...} but SimpleInjector has ThreadScopedLifestyle or AsyncScopedLifestyle. Which one do I use?

If I'm not mistaken, an Azure Worker Role is a short-lived application, that gets kicked off to do one simple thing and than dies quickly, just like you would with a Console Application.

Considering DI, this makes the development of a Worker Role very similar to that of a Console application. This means:

  • The application is short-lived
  • Will only run one request (compared to running multiple requests in parallel as happens with web services/applications)
  • There is a limit set of dependencies that need to be registered.

What this means is that, since the application is single-threaded and short-lived, there is no need to use a scoped lifestyle (such as ThreadScopedLifestyle or AsyncScopedLifestyle ). Instead you could easily register all dependencies as singleton, resolve the root, call its method, and dispose the container.

If however, your application lives for a long time, and goes on in an endless loop, you typically want to simulate the notion of a 'request'. This typically means that every loop is a request, and during that request you resolve from the container. Note that you only need a scoped lifestyle if you actually have scoped registrations. If not, you don't have to wrap the request in a scope. If you have scoped registrations, you'll have to wrap each request in a scope, just as you did in your example.

Reference-2 has static Main class, static readonly Container, and static contructor. Do I define static Container for Worker role? what about static constructor for dependency registration?

Although static constructors give thread-safety and singleton behavior for free, they do however complicate debugging in case an exception is thrown, since the real error is wrapped in a TypeInitializationException . Your cctor however does make it easy to initialize your static Container field. It's fine to have the Container in a static field.

However, since these types of applications are really small with only a small set of Dependencies, do container to not use a DI Container at all . Instead use Pure DI . This might sound like a strange advice from someone who develops and maintains a DI Container, but I found it more practical to use Pure DI for small applications, especially when everything your register is singleton anyway. The advantages are:

  • You have compile-time support over the construction of your object graph
  • It prevents having to use a third party tool
  • There is a lot of overhead with DI Containers when it comes to the application's initialization phase, while Worker Roles should start up quickly.
  • Can be considerably easier for small object graphs.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM