Внедрение внутренних классов в функции веб-заданий Azure


Есть ли способ для класса по умолчанию Functions, который входит в проекты WebJob, быть internal? Мы используем активатор заданий для введения через Unity некоторых зависимостей, которые являются internal, что требует, чтобы класс Functions также был internal. При запуске веб-задания мы видим следующую ошибку:

No job functions found. Try making your job classes and methods public. If you're using binding extensions (e.g. ServiceBus, Timers, etc.) make sure you've called the registration method for the extension(s) in your startup code (e.g. config.UseServiceBus(), config.UseTimers(), etc.).

Когда мы делаем все зависимости public, это работает нормально, поэтому я знаю, что нет ничего плохого в моих триггерах или конфигурации хоста задания.

Вот моя программа. класс:

class Program
{
    static void Main()
    {
        var config = new JobHostConfiguration
        {
            JobActivator = new Activator(new UnityContainer())
        };
        config.UseServiceBus();
        var host = new JobHost(config);
        host.RunAndBlock();
    }
}

Вот упрощенная версия моего класса функций:

internal class Functions
{
    private readonly IMyInternalDependency _dependency;

    public Functions(IMyInternalDependency dependency)
    {
        _dependency = dependency;
    }

    public function DoSomething([ServiceBusTrigger("my-queue")] BrokeredMessage message)
    {
        // Do something with the message
    }
}
2 3

2 ответа:

Вы должны сделать класс Functions общедоступным. Похоже, именно так и работает Azure WebJobs. Вам не нужно выставлять свои конкретные внутренние классы публично. Только интерфейсы:

public interface IDoStuffPublically
{
    void DoSomething();
}

interface IDoStuffInternally
{
    void DoSomething();
    void DoSomethingInternally();
}

class DoStuff : IDoStuffPublically, IDoStuffInternally
{
    public void DoSomething()
    {
        // ...
    }

    public void DoSomethingInternally()
    {
        // ...
    }
}

А затем ваш Functions класс:

public class Functions
{
    public Functions(IDoStuffPublically stuff)
    {
        _stuff = stuff;
    }

    private IDoStuffPublically _stuff;

    // ...
}

И Unity сделает что-то вроде этого:

var job = new Functions(new DoStuff());

Дейв прокомментировал:

Меня расстраивает, что я не могу просто установить внутренние компоненты, видимые для WebJob SDK...

Вы могли бы это сделать... miiiiiiiiiight быть в состоянии...

Существует способ для сборки или исполняемого файла предоставить другой сборке разрешение на доступ к внутренним членам. Я уже делал это раньше в библиотеке классов, чтобы мои модульные тесты могли вызывать внутренние методы класса в рамках настройки модульного теста.

Если вы знаете, какая сборка в Azure WebJobs на самом деле создает экземпляр класса функций, а также сборку, которая вызывает методы этого класса, вы можете добавить их в белый список. сборки.

Crack open AssemblyInfo.cs и добавить одну или несколько строк:

[assembly: InternalsVisibleTo("Microsoft.Azure.Something.Something")]

Ссылка: InternalsVisibleToAttribute class

Чтение по теме: советы .Net-использование атрибута InternalsVisibleTo для тестирования непубличных методов

Хотя я не уверен, какие сборки вам нужно будет добавить.

При использовании триггеров с WebJob SDK вы никогда не регистрируете выполняемые функции.

Когда jobhost запускается (new JobHost(config).RunAndBlock()), он обнаруживает функции, которые будут выполняться на основе атрибутов параметров.

Давайте посмотрим на ваш код:

    var config = new JobHostConfiguration
    {
        JobActivator = new Activator(new UnityContainer())
    };
    config.UseServiceBus();

Поскольку вы указали, что хотите использовать servicebus, при запуске jobhost будет обнаруживать и регистрировать (индексировать) все функции, имеющие параметр с атрибутом ServiceBusTrigger.

Я предполагаю, что SDK использует что-то вроде MemberInfo.GetCustomAttributes индексирует функции, поэтому не знаю, легко ли (возможно и) получить атрибуты из внутреннего класса.