如何使用 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
的更多信息
我正在尝试设置一个简单的 .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
的更多信息