如何将简单注入器用于 Azure 辅助角色

how to use Simple Injector to Azure Worker Role

我参考了几个文件,但我需要正确的实施才能正确执行。

参考资料

  1. 工人角色统一:https://alexandrebrisebois.wordpress.com/2013/04/14/building-windows-azure-services-without-compromising-testability/

  2. 控制台应用程序的 SimpleInjector:http://simpleinjector.readthedocs.io/en/latest/consoleintegration.html

我的问题

  1. Reference-1, Unity 使用 using (var uc = new UnityContainer()){...} 但 SimpleInjector 有 ThreadScopedLifestyleAsyncScopedLifestyle。我用哪一个?

  2. Reference-2 有 static Main class、static readonly Containerstatic contructor。我是否为 Worker 角色定义 static Containerstatic constructor 依赖注册怎么样?

  3. 我实现如下我的实现部分。这段代码实现正确吗?

参考代码

参考文献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();
    }
}

参考文献 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");
         }
     }
 }

我的实现

我认为 (1) Container 足以成为 static,(2) OnStart 是注册服务的好地方,并且 (3) 我想要的服务实例是每个循环创建和处置。

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

注意:我不知道上面的代码是否有效。

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

如果我没记错的话,Azure Worker Role 是一个短暂的应用程序,它被启动去做一件简单的事情然后很快就死掉,就像你使用控制台应用程序一样。

考虑到 DI,这使得辅助角色的开发与控制台应用程序的开发非常相似。这意味着:

  • 应用程序是短暂的
  • 只会 运行 一个请求(与 运行 并行处理多个请求相比,网络 services/applications)
  • 需要注册的依赖项数量有限。

这意味着,由于应用程序是单线程的且生命周期很短,因此无需使用作用域生活方式(例如 ThreadScopedLifestyleAsyncScopedLifestyle)。相反,您可以轻松地将所有依赖项注册为单例、解析根、调用其方法并处置容器。

但是,如果您的应用程序存在很长时间,并且会无限循环,您通常希望模拟 'request' 的概念。这通常意味着每个循环都是一个请求,并且在该请求期间您从容器中解析。请注意,如果您确实有范围内的注册,则只需要范围内的生活方式。如果不是,您不必将请求包装在一个范围内。如果您有范围注册,则必须将每个请求包装在一个范围内,就像您在示例中所做的那样。

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?

虽然静态构造函数免费提供线程安全和单例行为,但是它们确实使调试复杂化以防抛出异常,因为真正的错误包含在 TypeInitializationException 中。但是,您的 cctor 确实可以轻松初始化静态 Container 字段。在静态字段中使用 Container 很好。

但是,由于这些类型的应用程序非常小,只有一小部分依赖项,所以容器完全使用 DI 容器。而是使用 Pure DI。这听起来像是来自开发和维护 DI 容器的人的奇怪建议,但我发现将 Pure DI 用于小型应用程序更实用,尤其是当您的寄存器中的所有内容都是单例时。优点是:

  • 您对对象图的构建有编译时支持
  • 它避免了必须使用第三方工具
  • 当涉及到应用程序的初始化阶段时,DI 容器有很多开销,而工作者角色应该快速启动。
  • 对于小对象图来说会容易得多。