我正在尝试设置一个使用 Unity Container 5 的简单 .NET Core 3.1 项目(https://github.com/unitycontainer/unity).
我添加了对最新 Unity Configuration 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:
{"类型名称或别名 Implements.ImplementationN, 实施无法解决。请检查您的配置 文件并验证此类型名称。"}
我已将代码上传到 GitHub。
附注Visual Studio 2019 16.4.4 企业版、Windows 10 1909 x64 专业版
P.P.S。为 .NET Framework 4.8 编译的相同代码工作正常 - GitHub
为了澄清更多 - 我需要一种没有任何项目引用 Implements.dll 的方法,我应该能够更改特定的实现(通过更改 config.json)而无需重新编译。
我发现这更像是一个“.NET Core 程序集加载”问题,而不是 IoC 容器问题。
长话短说,如果您的应用程序没有专门引用该程序集,您需要告诉 .NET Core 程序集加载器从哪里获取它即使它位于您的 BIN 文件夹中。
因此,如果您(像我一样)不想拥有一个引用您需要的all实现库的引导库,但您想通过配置文件进行运行时配置 - 您应该执行以下操作。
来自 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.
// https://stackoverflow.com/questions/43918837/net-core-1-1-type-gettype-from-external-assembly-returns-null
//
// 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
的更多信息