如何使用 Unity Container 5 通过配置文件(运行时配置)使用外部插件

Howto use external plugins via config file (runtime configuration) with Unity Container 5

我正在尝试设置一个简单的 .NET Core 3.1 项目,该项目使用 Unity Container 5 (https://github.com/unitycontainer/unity).

我添加了对最新 Unity 配置 5.11.1 包 (https://www.nuget.org/packages/Unity.Configuration/) 的引用。

然后我用最简单的配置文件创建了界面、实现和测试应用程序:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration" />
  </configSections>
  <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <container>
      <register
        type="Interfaces.InterfaceN, Interfaces"
        mapTo="Implementations.ImplementationN, Implementations">
      </register>
    </container>
  </unity>
</configuration>

但我得到 System.InvalidOperationException

{"The type name or alias Implementations.ImplementationN, Implementations could not be resolved. Please check your configuration file and verify this type name."}

我已将我的代码上传到 GitHub。感谢任何帮助。

P.S. Visual Studio 2019 16.4.4 企业版,Windows 10 1909 x64 专业版

P.P.S..NET Framework 4.8 编译的相同代码工作正常 - GitHub

更新: 澄清更多 - 我需要一个没有任何项目引用 Implementations.dll 的提议,我应该能够无需重新编译即可更改特定实现(通过更改 config.json)。

我发现这更像是一个“.NET Core 程序集加载”问题,而不是 IoC 容器问题。

长话短说,如果程序集没有被您的应用程序专门引用,您需要告诉 .NET Core 程序集加载程序从哪里获取它即使它在您的 BIN 文件夹中.

因此,如果您(像我一样)不想拥有引用您需要的 所有 实现库的 bootstrap 库,但您想要运行时配置通过配置文件 - 您应该执行以下操作。

来自 Autofac IoC 示例存储库:

// THIS IS THE MAGIC!
// .NET Core assembly loading is confusing. Things that happen to be in your bin folder don't just suddenly
// qualify with the assembly loader. If the assembly isn't specifically referenced by your app, you need to
// tell .NET Core where to get it EVEN IF IT'S IN YOUR BIN FOLDER.
// 
//
// The documentation says that any .dll in the application base folder should work, but that doesn't seem
// to be entirely true. You always have to set up additional handlers if you AREN'T referencing the plugin assembly.
// https://github.com/dotnet/core-setup/blob/master/Documentation/design-docs/corehost.md
//
// To verify, try commenting this out and you'll see that the config system can't load the external plugin type.
var executionFolder = Path.GetDirectoryName(typeof(Program).Assembly.Location);
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(executionFolder, $"{assembly.Name}.dll"));
 };

然后是下面的代码

var container = new UnityContainer().LoadConfiguration();

var type = container.Resolve<InterfaceN>();

工作得很好。

P.S. 来自 Microsoft

的更多信息