使用NoAutomaticTrigger时,Azure WebJobs SDK中的依赖注入?

时间:2017-11-12 19:02:55

标签: c# azure dependency-injection azure-webjobs azure-webjobssdk

我正在构建一个将持续运行的Azure WebJob。我希望WebJob使用与ASP.NET Core相同的DI风格。我找到了关于如何使用自定义IJobActivator使DI / IoC正常工作的答案(Dependency injection using Azure WebJobs SDK?)。我还找到了这个答案(Azure WebJobs - No functions found - How do I make a trigger-less job?)关于使用NoAutomaticTrigger来配置连续运行的Web作业。

问题是NoAutomaticTrigger方法使用的静态方法与DI / IoC不兼容。我认为这是因为没有任何东西会导致使用NoAutomaticTrigger方法解析服务(如队列消息)。我觉得ITypeLocator可能是一条前进的道路,但这只是一种预感。

其他NoAutomaticTrigger示例中使用的JobHost.Call方法仅限于静态方法。如何通过DI解析并通过在Program.cs中调用JobHost(或其他方法)调用来解析服务?

Iza Eddi-son Atsou在下面提出的解决方案有效,只有一个皱纹。我习惯通过服务上的接口注册我的服务。像

这样的东西
serviceCollection.AddSingleton<IApplication, Application>();

这个问题是如果接口上有NoAutomaticTrigger属性,SDK会爆炸。解决方案是将属性添加到类中,并将类注册为自身。

serviceCollection.AddSingleton<Application>();

一旦做出改变,答案中的解决方案就会很有效。

2 个答案:

答案 0 :(得分:2)

WebJobs SDK现在支持触发的实例方法,而不仅仅是静态方法。 NoAutomaticTrigger方法不再需要是静态的。更新SDK,使用您找到的自定义IJobActivator方法,并记住注册函数类,当然还有其他依赖项。

示例程序类:

class Program
{

    static void Main()
    {
        var container = new UnityContainer();

        //the instance to be injected
        var systemClient = new JobSystemClient
        {
            UserName = "admin",
            PassWord = "admin1234"
        };

        container.RegisterInstance<ISystemClient>(systemClient);

        //Registration of the Functions class
        container.RegisterType<Functions>();            

        var activator = new UnityJobActivator(container);

        var config = new JobHostConfiguration();
        config.JobActivator = activator;            

        var host = new JobHost(config);
        // The following code will invoke a function called ManualTrigger and 
        // pass in data (value in this case) to the function
        host.Call(typeof(Functions).GetMethod("ManualTrigger"), new { value = 20 });

        host.RunAndBlock();

    }
}

示例函数类:

public class Functions
{
    private readonly ISystemClient _systemClient;
    public Functions(ISystemClient systemClient)
    {
        _systemClient = systemClient;
    }

    //Not static anymore
    [NoAutomaticTrigger]
    public void ManualTrigger(TextWriter log, int value, [Queue("queue")] out string message)
    {
        log.WriteLine("Function is invoked with value={0}", value);
        message = value.ToString();         
        log.WriteLine("username:{0} and password:{1}", _systemClient.UserName, _systemClient.PassWord);
    }
}

这是输出:

Found the following functions:
TestWebJob.Functions.ManualTrigger
Executing 'Functions.ManualTrigger' (Reason='This function was programmatically called via the host APIs.', Id=bf9aedc0-89d1-4ba0-a33e-9b23e0d7b8a2)
Function is invoked with value=20
Following message will be written on the Queue=20
username:admin and password:admin1234
Executed 'Functions.ManualTrigger' (Succeeded, Id=bf9aedc0-89d1-4ba0-a33e-9b23e0d7b8a2)
Job host started

答案 1 :(得分:1)

AFAIK,NoAutomaticTrigger属性在两种情况下很有用:带触发器的函数阻止自动调用触发器,允许手动轮询。没有其他属性的函数将函数标记为可用的作业函数。在这两种情况下,JobHost都不会自动调用标记有此属性的函数(在RunAndBlock期间)。相反,必须使用Call方法手动调用它们。并且,此属性也可用于非静态方法。

这里有一些关于使用Azure WebJobs和依赖注入的相关文章,你可以参考它们: http://www.ryansouthgate.com/2016/05/10/azure-webjobs-and-dependency-injection/http://www.jerriepelser.com/blog/using-autofac-and-common-service-locator-with-azure-webjobs