将内部 类 注入 Azure WebJob 函数

Injecting Internal Classes into Azure WebJob Functions

有什么方法可以将 WebJob 项目中的默认 Functions class 设为 internal?我们正在使用作业激活器通过 Unity 注入一些 internal 的依赖项,这要求 Functions class 也是 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:

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

这是我的函数的简化版本 class:

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
    }
}

你必须Functionsclasspublic。这似乎正是 Azure WebJobs 的工作方式。您不需要公开具体的内部 classes publicly。仅接口:

public interface IDoStuffPublically
{
    void DoSomething();
}

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

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

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

然后是你的 Functions class:

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

    private IDoStuffPublically _stuff;

    // ...
}

Unity 会做这样的事情:

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

戴夫评论道:

It's frustrating that I cannot simply set the internals visible to the WebJob SDK...

可能能够完成这个...miiiiiiiiiight能够...

程序集或可执行文件有一种方法可以授予另一个程序集访问内部成员的权限。我之前在 class 库上完成过此操作,以允许我的单元测试调用 class 上的内部方法作为设置单元测试的一部分。

如果您知道 Azure WebJobs 中的哪个程序集实际创建了您的 Functions class 实例,以及调用该方法的程序集 class,您可以将这些程序集列入白名单。

破解AssemblyInfo.cs并添加一行或多行:

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

参考:InternalsVisibleToAttribute class

相关阅读:.Net Tips – using InternalsVisibleTo attribute to help testing non-public methods

不过我不确定您需要添加哪些程序集。

在 Webjob SDK 中使用触发器时,您无需注册要执行的函数。

当 jobhost 启动时 (new JobHost(config).RunAndBlock()),它会根据参数属性发现要执行的函数。

让我们看看您的代码:

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

因为您指定要使用服务总线,所以当 jobhost 启动时,它会发现并注册(索引)所有具有 ServiceBusTrigger 属性参数的函数。

我假设 SDK 使用 MemberInfo.GetCustomAttributes 之类的东西来索引函数,所以不知道从内部 class.[=14 获取属性是否(可能且)容易=]