【问题标题】:How do I load an ASP.NET Core controller from a plugin assembly using Autofac configuration?如何使用 Autofac 配置从插件程序集中加载 ASP.NET Core 控制器?
【发布时间】:2019-03-11 23:32:17
【问题描述】:

我是 .NET Core 的新手,但我一直在 ASP.NET 中使用 Autofac,我正在尝试使用 Autofac 配置 as I did in ASP.NET 注册控制器。我阅读了一堆代码示例,但似乎 .NET Core 的 Autofac 手册不适用于 .NET Core 2.1。

我的目标是使用 Autofac 配置从另一个项目加载控制器。有什么可行的例子吗?

我在 .NET 4.7 中使用 Autofac.Configuration 将控制器作为插件注入,但在 .NET Core 2.1 中包含 Autofac.Configuration 失败 我在其他项目中创建了小型 ASP.NET Core 项目和几个控制器。这个想法是通过 Autofac.Configuration 将这些控制器包含在 ASP.NET Core 项目中。

这是我的 autofac.json 配置文件

{
  "components": [{
    "type": "Controllers.UserController, Controllers",
    "services": [{"type": "Common.IController, Common"}]
  }]
}

这是来自 Startup.cs 的代码

public IServiceProvider ConfigureServices(IServiceCollection services)
{
  services.AddMvc().AddControllersAsServices();
  var builder = new ContainerBuilder();
  var mseConfig = new ConfigurationBuilder(); 
  mseConfig.AddJsonFile("autofac.json");
  var module = new ConfigurationModule(mseConfig.Build()); 
  builder.RegisterModule(module);
  builder.Populate(services);
  var container = builder.Build();
  return new AutofacServiceProvider(container);
}

我收到的错误是“System.InvalidOperationException: '找不到类型'Controllers.UserController, Controllers'。它可能需要装配资格,例如“MyType, MyAssembly”。'”

Controllers.dll 文件存在于 ASP.NET Core 项目的 bin 文件夹中。

【问题讨论】:

  • 只是一个问题,为什么不在 .NET Core 中使用提供的 DI 容器?
  • @ChirdeepTomar 因为原生 DI 不支持属性注入等许多功能。
  • @ChirdeepTomar:因为reasons。
  • @ChirdeepTomar - 就像 Alex Herman 所说,原生 DI 不支持许多花哨的功能。
  • 为了帮助您解决问题,我们需要更多信息。 The "How to ask a question" docs 可以在这里为您提供帮助,you cross-posted in the issue 也可以为您提供一些帮助:最小的重现,带有堆栈跟踪的完整异常(如果有),您尝试过的事情,您寻找答案的地方。一个准确的标题也会有所帮助 - 并不是 Autofac.Config 不能与 .NET Core 一起使用,而是您无法让动态加载的控制器工作。

标签: .net asp.net-core .net-core autofac asp.net-core-2.1


【解决方案1】:

我创建了a working example in the Autofac Examples repo。

问题在于 .NET Core 程序集加载器如何不只是假设您的 bin 文件夹中的东西是可加载的。 您绝对需要告诉 .NET Core 的程序集加载器从哪里获取不可加载的程序集直接引用。这不是 Autofac 配置的东西,那是 .NET Core,新的加载器系统相当混乱。

当 Autofac.Configuration 尝试从未引用的程序集中加载配置的类型时,.NET Core 加载程序无法识别该程序集并引发您需要处理的事件以便它可以工作。一个简单的解决方案如示例所示:

AssemblyLoadContext.Default.Resolving += (AssemblyLoadContext context, AssemblyName assembly) =>
{
  // DISCLAIMER: NO PROMISES THIS IS SECURE. You may or may not want this strategy. It's up to
  // you to determine if allowing any assembly in the directory to be loaded is acceptable. This
  // is for demo purposes only.
  return context.LoadFromAssemblyPath(Path.Combine(Directory.GetCurrentDirectory(), $"{assembly.Name}.dll"));
};

您可以从您的代码中进行的最简单的测试:如果您执行Type.GetType("MyNamespace.MyType, MyAssembly") 并得出null,则.NET Core 找不到您的类型,您需要处理程序集加载。

有关详细信息,您应该搜索有关 .NET Core 程序集加载工作原理的问题/答案。

更新基于评论线程:

JSON 配置与控制器注册的程序集扫描样式注册结合起来似乎有些混乱。这里似乎也有一些关于插件程序集处理的混淆。我认为这些事情的结合使得问题的答案似乎不存在,而实际上它是......或者可能被问到的问题并不清楚意图是什么。

当我读到它时,有两件事需要:

  • 在应用程序集中自动注册控制器。
  • 在外部插件程序集中注册其他控制器。

我对这个问题的理解可能已经离题了,但这就是它的阅读方式,所以我只能继续说下去。

首先,如果可以,我真的建议避免使用插件。我知道这是一件非常酷的事情,可能是您的应用程序需要的功能,但正如我在原始答案中所指出的,插件和程序集加载与原始 .NET 框架中的方式确实不同。但是,让我们继续吧。

当您执行services.AddControllers() as shown in this example 之类的操作时,它将注册应用程序集中的所有控制器。如您所见,它不会拾取插件。该示例确实适用于应用程序程序集中的控制器,并且可以替代 WebAPI 2 RegisterApiControllers()。

关于 .NET Core 的一些注意事项可能并不明显,即整个 DI 系统和 Web 应用程序托管机制已被简化和规范化。控制器没有像旧的 Web API 或 ASP.NET MVC 那样的“特殊处理”。您不再使用RegisterType<MyController>().As<IController>() 或类似的东西。您只需注册您想要的任何类型。因此,如果您在 Autofac 中寻找类似 RegisterApiControllers() 的东西,您将找不到它。 The Autofac ASP.NET Core docs cover a lot of the differences 这可以帮助澄清一些问题。

这让我们回到了如何通过配置注册事物的问题。 我认为您的配置是正确的。 我可以看到您可能需要不注册控制器As 任何东西;或者添加类型本身,因为 .NET Core 中没有通用的控制器接口。

{
  "components": [{
    "type": "Controllers.UserController, Controllers",
    "services": [
      {"type": "Common.IController, Common"}
      {"type": "Controllers.UserController, Controllers"}
    ]
  }]
}

这给我们带来了异常。您发布了您看到的异常,我已经解释了原因 - .NET Core 的程序集加载机制不像经典 .网。 I already pointed you to a working plugin example. 没有针对 ASP.NET Core 的具体示例,因为 ASP.NET Core 与任何 .NET Core 控制台应用程序或其他任何东西相比,没有具体的支持或差异。这是一回事。 .NET Core == ASP.NET Core == 自托管 .NET Core 服务。您只需要在您的 ASP.NET Core 应用程序中处理程序集加载部分。

这就是问题的全部内容。关于程序集扫描的问题中没有提到任何其他内容(这不是配置,也不是您可以通过配置指定的内容)。使用 MEF 没有任何意义(这是 AddApplicationPart() 在评论线程中不断得到注意的东西)。

如果这不足以回答您想要完成的任务,我很抱歉。该问题询问如何通过配置注册控制器并记录我解决的异常。评论线程不断回到程序集扫描,这不是配置,但可以通过程序集扫描来解决。异常指出找不到程序集,我解释说程序集加载很复杂,并且是控制器注册的正交主题,如果您应该查找有关 .NET Core 程序集加载的更多信息需要它,因为它不是 Autofac 涵盖的内容,ASP.NET Core 也没有,而且在程序集加载方面没有任何特定于 ASP.NET Core 的内容。

我认为这里没有其他可以提供的,所以,如果这还不够,我很抱歉。

【讨论】:

  • 是否有示例如何使用 autofac 配置文件 (JSON) 注册控制器?我读了autofac.readthedocs.io,但没有这样的例子:(
  • 控制器与注册的任何其他类型没有任何不同。有如何通过配置注册事物的示例;它不必是显示控制器的特定示例。但是,如果控制器在不同的程序集中,您将遇到这样的程序集加载挑战,而且,控制器 并没有什么特别之处。您仍然必须确保程序集已加载,而 Autofac 不会为您做这些事情。您负责程序集加载。
  • 感谢您的耐心等待。我注册任何其他类都没有问题,但由于我缺少 Autofac.WebApi2(它与 .NET Core 不兼容)我不知道如何像在 .NET FW 中那样注册控制器我想到的唯一方法就是这个 var程序集 = 程序集.LoadFile(路径); services.AddControllers().AddApplicationPart(程序集).AddControllersAsServices();但这不是它应该工作的方式。
  • 似乎您所问的问题与此处所问的问题不同,或者如果不是,则至少需要对您正在尝试做什么以及什么不起作用的额外解释 - 显示您尝试过的 JSON 配置,以及您要注册的控制器类型;显示您在容器中注册配置的部分等。足够有人可以尝试复制您正在做的事情并查看它为什么不起作用。
  • 同一个问题:如何使用JSON配置注册控制器?第一个问题是程序集加载(这似乎在 .NET 5 中得到了解决),但控制器注册仍然存在问题。没有一个示例如何做到这一点,我不确定是否可能。在 .NET FW 中,我依赖 Autofac.WebApi2 和“RegisterApiControllers”方法,但我不能在 .NET 5 中使用这个库或这种方法。所以问题是:如何使用 JSON 配置文件注册控制器?跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-02
  • 1970-01-01
  • 2021-08-10
  • 2016-11-02
  • 2020-07-14
  • 2016-12-13
  • 2020-02-28
相关资源
最近更新 更多