Azure webjobs - Unity - 如何将范围内的依赖项注入其他类

时间:2018-02-28 16:34:28

标签: c# dependency-injection azure-webjobs

我正在尝试在Azure webJob中注入依赖项。我目前正在使用IJobActivator来创建和解析统一容器。

// Job setup
static void Main()
{
    var config = new JobHostConfiguration();
    config.JobActivator = new JobActivationHandler();

    var host = new JobHost(config);
    host.RunAndBlock();
}

我当前正在传递容器本身,以创建子容器,并解析作业范围中的依赖关系。

internal class JobActivationHandler : IJobActivator
{
    private IUnityContainer container;

    public JobActivationHandler()
    {
        container = new UnityContainer();

        container.RegisterType<IDependency, Dependency>();
        // I am passing the container itself, to register job specific 
        // dependencies, pls see the webjob implementation.
        container.RegisterInstance<IUnityContainer>(container);
    }

    public T CreateInstance<T>()
    {
        return container.Resolve<T>();
    }
}

// WebJob
 private readonly IUnityContainer jobContainerInstance;

    public ProcessDataJob(IUnityContainer unityContainer)
    {
      // Create a child container for this job instance, 
      // so that the depencies are scoped for current job.
        this.jobContainerInstance = unityContainer.CreateChildContainer();
    }

     public async Task ProcessDataJob(
        [QueueTrigger("%Queue:DataQueue%")] DataObject dataObject ,
        [Blob("%Blob:LogOutput%/{TenantId}/{JobId}.txt")] TextWriter blobLogOutput)
    {
          /* Here i am creating a log writer or other service, 
          that are job instance specific, and this dependency 
          should be injected to other classes.
          This service is instance specific, so i cannot instantiate it in 
          the root container*/
         logWriter = CreateLogger(dataObject);
         jobContainerInstance.RegisterInstance<ILogWriter>(logWriter);

         /* The only way i can inject this dependency is to resolve a class 
         out of this child container itself. */
            var classB = jobContainerInstance.Resolve<ClassB>()
    }


// The dependency ILogWriter is properly resolved. 
// But i need to pass on the container as well, if i need this dependency to 
// be injected in class C
ClassB
{
   public ClassB(IUnityContainer unityContainerInstance, ILogWriter logWriter)
    {
       var classC = unityContainerInstance.Resolve<ClassC>();
    }
}

ClassC
{
   public ClassC(IUnityContainer unityContainerInstance, ILogWriter logWriter)
    {

    }
}

有没有更好的方法来解决这个问题,而不是将子容器级联到所有必须使用已解决的依赖性的类?

1 个答案:

答案 0 :(得分:0)

以下是使用Microsoft.Extensions.DependencyInjection代替统一的示例:

// Job setup
static void Main()
{
    var services = new ServiceCollection();
    // Register your services here
    services.AddSingleton<ClassB>();
    services.AddScoped<ClassC>();

    var serviceProvider = services.BuildServiceProvider();
    var config = new JobHostConfiguration
    {
        JobActivator = new JobServiceProviderActivator(serviceProvider)
    };

    var host = new JobHost(config);
    host.RunAndBlock();
}

以下是服务提供商:

public class JobServiceProviderActivator : IJobActivator
{   
    private readonly IServiceProvider provider;

    public JobServiceProviderActivator(IServiceProvider provider)
    {
        this.provider = provider;
    }

    public T CreateInstance<T>()
    {
        return provider.GetService<T>();
    }
}

注册后,您可以将类注入到作业类构造函数中:

public ProcessDataJob(ClassB classB)
{
}