使用 Unity 通过 Azure WebJob 从另一个项目注入依赖项

Using Unity to inject dependency from another project with Azure WebJob

我的解决方案中有两个项目 - 一个 Web 项目和一个控制台应用程序。

Web 项目

在我的网络项目中,我有以下工作:

public class TestService : BaseService {
    private BrowseService _browseService;
    public TestService(BrowseService browseService) {
        _browseService = browseService;
    }

    public ApiResponseDto DoStuff(string username) {

        using (var db = new AppContext()) {
            var user = db.FindUser(username);
            // do stuff with _browseService here
        }
    }
 }

我在这里使用 Unity 进行 DI。

控制台应用程序

现在,我从我的控制台应用程序引用我的 Web 项目并执行以下操作:

public class Functions {
    private TestService _testService;
    public Functions(TestService testService) {
        _testService = testService;
    }

    public static void ProcessStuff([QueueTrigger("my-queue")] string userId) {
        using (var db = new AppContext()) { // works
            _testService.DoStuff(userId) // _testService isn't available
        }
    }

问题

如何让 DI 在我的控制台应用程序中工作?我添加了 Unity,然后执行此操作:

    static void Main() {
        var container = new UnityContainer();
        DependencyResolver.SetResolver(new UnityDependencyResolver(container));
        var host = new JobHost();
        // The following code ensures that the WebJob will be running continuously
        host.RunAndBlock();
    }

但是,上面的构造函数永远不会被命中,并且 _testService 永远不可用。

更新

我尝试了以下操作:

static void Main() {
    var container = new UnityContainer();
    var host = container.Resolve<JobHost>().
    host.RunAndBlock();
}

但是我得到一个例外:

Microsoft.Practices.Unity.ResolutionFailedException was unhandled
_HResult=-2146233088 _message=Resolution of the dependency failed, type = "Microsoft.Azure.WebJobs.JobHost", name = "(none)". Exception occurred while: while resolving. Exception is: InvalidOperationException - The type String cannot be constructed. You must configure the container to supply this value. ----------------------------------------------- At the time of the exception, the container was:

Resolving Microsoft.Azure.WebJobs.JobHost,(none) Resolving parameter "configuration" of constructor Microsoft.Azure.WebJobs.JobHost(Microsoft.Azure.WebJobs.JobHostConfiguration configuration) Resolving Microsoft.Azure.WebJobs.JobHostConfiguration,(none) Resolving parameter "dashboardAndStorageConnectionString" of constructor Microsoft.Azure.WebJobs.JobHostConfiguration(System.String dashboardAndStorageConnectionString) Resolving System.String,(none)

HResult=-2146233088 IsTransient=false Message=Resolution of the dependency failed, type = "Microsoft.Azure.WebJobs.JobHost", name = "(none)". Exception occurred while: while resolving. Exception is: InvalidOperationException - The type String cannot be constructed. You must configure the container to supply this value.

更新 2

我现在对这个问题有以下看法

class Program {
    static void Main() {
        var container = new UnityContainer();
        var config = new JobHostConfiguration {
            JobActivator = new MyActivator(container)
        };
        var host = new JobHost(config);
        // The following code ensures that the WebJob will be running continuously
        host.RunAndBlock();
    }
}

public class MyActivator : IJobActivator {
    private readonly IUnityContainer _container;

    public MyActivator(IUnityContainer container) {
        _container = container;
    }

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

但是,_testService 仍然是 null,Functions 的注入构造函数永远不会执行。

DependencyResolver 是一个 MVC 结构;它不在控制台应用程序中使用。要完成这项工作,请将您的主要方法更改为:

static void Main() {
        var container = new UnityContainer();
        var host = container.Resolve<JobHost>().
        host.RunAndBlock();
    }

然后,只要你使用构造函数注入,一切都应该按预期工作。

根据您的代码,我已经在我这边测试并解决了。请尝试按照以下代码查看是否对您有所帮助:

Web 项目

public class TestService : BaseService
{
    private BrowseService _browseService;
    public TestService(BrowseService browseService)
    {
        _browseService = browseService;
    }

    public string DoStuff(string username)
    {
        return _browseService.DoStuff(username);
    }
}

public class BaseService { }

public abstract class BrowseService
{
    public abstract string DoStuff(string username);
}

public class MyBrowseService : BrowseService
{
    public override string DoStuff(string username)
    {
        return string.Format("MyBrowseService.DoStuff is invoked with value={0}", username);
    }
}

控制台应用程序

1)Functions.cs

public class Functions
{
    private static TestService _testService;
    public Functions(TestService testService)
    {
        _testService = testService;
    }

    public void ProcessStuff([QueueTrigger("my-queue")] string userId)
    {
        try
        {
            Console.WriteLine("ProcessStuff is invoked with value={0}", userId);
            string result = _testService.DoStuff(userId);
            Console.WriteLine("ProcessStuff return the result:\r\n{0}", result);
        }
        catch (Exception e)
        {
            Console.WriteLine("ProcessStuff executed with errors.\r\n{0}\r\n{1}", e.Message, e.StackTrace);
        }
    }
}

注意:您应该将 WebJob 函数设置为实例函数而不是静态函数。

2)Program.cs

static void Main()
{
    UnityContainer container = new UnityContainer();
    container.RegisterType<BrowseService, MyBrowseService>();
    container.RegisterType<Functions>(); //Need to register WebJob class
    var config = new JobHostConfiguration()
    {
        JobActivator = new UnityJobActivator(container)
    };
    var host = new JobHost(config);
    host.RunAndBlock();
}

结果: