【问题标题】:Injecting Internal Classes into Azure WebJob Functions将内部类注入 Azure WebJob Functions
【发布时间】:2016-06-23 16:10:08
【问题描述】:

有没有办法让 WebJob 项目中的默认 Functions 类成为 internal?我们正在使用作业激活器通过 Unity 注入一些 internal 的依赖项,这要求 Functions 类也必须是 internal。运行 Web 作业时,我们看到以下错误:

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();
    }
}

这是我的 Functions 类的简化版本:

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

【问题讨论】:

  • 我对 WebJobs 了解不多,但是您可以让私有或内部类实现公共接口,并将该对象作为其接口传递。
  • 你能发布一些代码,或者代码示例以获得一些上下文吗?

标签: c# azure unity-container azure-webjobs


【解决方案1】:

您必须公开 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 中的哪个程序集实际创建了 Functions 类的实例,以及调用该类方法的程序集,您可以将这些程序集列入白名单。

打开 AssemblyInfo.cs 并添加一行或多行:

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

参考:InternalsVisibleToAttribute class

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

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

【讨论】:

  • 令人沮丧的是,我不能简单地设置 WebJob SDK 可见的内部结构,但是哦,好吧。这似乎是最好的解决方案。谢谢。
  • 在 AssemblyInfo.cs 文件中,您可以使 internals 对另一个程序集可见。我想知道这是否可行,只要您知道 WebJob 是从哪个 Assembly 运行...
  • @Dave:我已经更新了我的问题,提供了可能的解决方案。
  • 我实际上在发布之前尝试过,但无济于事。当然,我可能没有偶然发现正确的程序集名称,但我尝试了以下方法但它们不起作用:Microsoft.Azure.WebJobs、Microsoft.Azure.WebJobs.Host、Microsoft.Azure.WebJobs、Microsoft.Azure。 WebJobs.ServiceBus 和 Microsoft.Azure.WebJobs.Host.Executors
【解决方案2】:

将触发器与 Webjob SDK 一起使用时,您永远不会注册要执行的函数。

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

让我们看看你的代码:

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

因为你指定要使用servicebus,所以jobhost启动时会发现并注册(索引)所有有ServiceBusTrigger属性参数的函数。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-09
    • 1970-01-01
    • 2018-06-28
    • 1970-01-01
    • 2022-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多