Внедрение зависимостей в Azure WebJobs SDK при использовании NoAutomaticTrigger?

Я создаю веб-задание Azure, которое будет работать непрерывно. Я хочу, чтобы веб-задание использовало тот же стиль внедрения зависимостей, что и ASP.NET Core. Я нашел этот ответ (Внедрение зависимостей с помощью SDK Azure WebJobs?) о том, как заставить DI/IoC работать с помощью пользовательского IJobActivator. Я также нашел этот ответ (Azure WebJobs — функции не найдены — как создать задание без триггера?) об использовании NoAutomaticTrigger для настройки непрерывно выполняющегося веб-задания.

Проблема в том, что подход NoAutomaticTrigger использует статические методы, что несовместимо с DI/IoC. Я предполагаю, что это связано с тем, что нет ничего, что могло бы вызвать разрешение службы с методом NoAutomaticTrigger (например, сообщение очереди). Я чувствую, что ITypeLocator может быть шагом вперед, но это всего лишь догадка.

Метод JobHost.Call, используемый в других примерах NoAutomaticTrigger, ограничен статическим методом. Как получить службу, которая разрешается через DI, которая разрешается и вызывается из вызова JobHost (или каким-либо другим методом) в Program.cs?


Решение, которое предложил Иза Эдди-сон Ацу ниже, работает, но с одним недостатком. Я привык регистрировать свои сервисы через интерфейс на сервисе. Что-то вроде

serviceCollection.AddSingleton<IApplication, Application>();

Проблема в том, что если атрибут NoAutomaticTrigger находится на интерфейсе, SDK взрывается. Решение состоит в том, чтобы добавить атрибут к классу и зарегистрировать класс как самого себя.

serviceCollection.AddSingleton<Application>();

После внесения этого изменения решение в ответе отлично работает.


person Erick T    schedule 12.11.2017    source источник


Ответы (2)


Пакет 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
person Iza Atsou    schedule 13.11.2017
comment
Спасибо! Мне пришлось немного переработать, так как я регистрировал класс, содержащий функцию, через интерфейс. - person Erick T; 14.11.2017
comment
Спасибо .. Я пропустил часть, где мне нужно было добавить Functions в сервисную коллекцию ... затем бум. Все заработало. Очень хорошо! Спасибо +1 - person Piotr Kula; 27.06.2018
comment
Было бы лучше, если бы вы предоставили версию SDK, которую вы просили обновить. На данный момент существует две версии: одна для ядра .Net (3.x) и другая для .Net (2.x). - person Hamza Khanzada; 19.08.2019

Насколько я знаю, атрибут 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

person Zhi Lv    schedule 13.11.2017