I'm trying to setup a simple .NET Core 3.1 project that uses Unity Container 5 (https://github.com/unitycontainer/unity).
I've added a reference to latest Unity Configuration 5.11.1 package (https://www.nuget.org/packages/Unity.Configuration/).
Then I've created interface, implementation and test app with a simplest config file:
<?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>
But I'm getting System.InvalidOperationException:
{"The type name or alias Implementations.ImplementationN, Implementations could not be resolved. Please check your configuration file and verify this type name."}
I've uploaded my code to GitHub.
P.S. Visual Studio 2019 16.4.4 Enterprise, Windows 10 1909 x64 Professional
P.P.S. Same code compiled for .NET Framework 4.8 works fine - GitHub
To clarify more - I need an approach without ANY project referencing Implementations.dll, I should be able to change specific implementation (via changing config.json) without recompilation.
I've found out this more a ".NET Core assembly loading" problem than an IoC container problem.
To cut a long story short, if the assembly isn't specifically referenced by your app, you need to tell .NET Core assembly loader where to get it EVEN IF IT'S IN YOUR BIN FOLDER.
So if you (like me) don't want to have a bootstrap library that references all implementation libraries that you need but you want to have runtime configuration via config file - you should do the following.
From Autofac IoC examples repository:
// 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"));
};
And after that the following code
var container = new UnityContainer().LoadConfiguration();
var type = container.Resolve<InterfaceN>();
is working like a charm.
P.S. Some more info from Microsoft