Hello everyone, I'm doing my very first steps with unity... obviously :-) I have the following projects (and their namespaces) within one visual studio solution - ConsoleApplication1 (ConsoleApplication1) - LoggingLibrary1 (dev.playground.logginglibrary1)
- LoggingLibrary2 (dev.playground.logginglibrary2) For testing purposes I went for automatic type lookups and added the following lines (only the first two or the last two are enabled at a time!): <namespace name="dev.playground.logginglibrary1"
/> <assembly name="dev.playground.logginglibrary1" /> <namespace name="dev.playground.logginglibrary2" /> <assembly name="dev.playground.logginglibrary2" /> ConsoleApplication1 tries to Resolve a type of ILogger.
The interface is defined in both LoggingLibrary assemblies. example: ILogger myLogger = container.Resolve<ILogger>(); So to be able to use intellisense and even compile the solution I need to add a reference from consoleapplication1 to one of the assemblies
containing the interface definition for ILogger. Everything works. However as soon as I changed the <namespace> and <assembly> unity configuration it won't run anymore. Unhandled Exception: System.InvalidOperationException: The type name or alias
ILogger could not be resolved. Please check your configuration file and verify this type name. It does work again as soon as I switch the assembly reference from ConsoleApplication1 to logginglibrary2 (instead of previously used logginglibrary1). This doesn't
exactly serve the purpose of Dependency Injection does it? So what am I doing wrong? The two LoggingLibrary projects and classes are exactly the same (apart from the assembly name/namespaces).
Let me see if I understand. You have the interface ILogger defined in two places, LoggingLibrary1 and LoggingLibrary2. You have ConsoleApplication1 referencing LoggingLibrary1, you have the unity config pointing at LoggingLibrary2, and that's when it's blowing
up? If I am not understanding correctly, then please let me know.
If this is your situation, it's pretty easy to explain, and isn't really a Unity issue. The thing is that the assembly a type is in is part of the full type name. That means that, even though the contents of the interfaces may be the same, dev.playground.logginglibrary1.ILogger
and dev.playground.logginglibrary2.ILogger are in fact different types as far as the CLR is concerned, and therefore when you try and resolve ILogger, it's specifically looking for the one in logginglibrary1. Since you didn't tell it to look there,
it doesn't and the resolve fails.
The real solution here is to move the interface out into a separate assembly so that everyone who uses it can reference that assembly in one place, and have a common interface definition to work from.
that of course make sense.
I followed your advice and my solution now looks like this:
- LoggingAssembly A (imagine there are further interchangeable assemblies B, C, D etc. This project has a reference to CommonInterfaces to implement the interface.)
- CommonInterfaces (contains the ILogger interface)
- Core (This project has a reference to CommonInterfaces to program against ILogger. This project makes use of Unity. Offers the encapsulated logging functionality throughout the solution.)
- Additional projects (have references to the Core assembly)
I realized I cannot configure my container programmatically because for this to work I'd need a reference from "Core" to "LoggingAssembly X", because I need the concrete implementations of ILogger (for example TraceLogger) to configure
my container. The types have to be known. However as soon as I add the reference from Core to LoggingAssembly X I lose the ability to interchange my logging assemblies. I always need to recompile "Core".
I thought design-time configuration was a solution to this. So I could add an assembly and a namespace to the lookup list and all the types are present at the point of time the container is configured. Unfortunately that didn't work out for me. I always
get a "type not found" exception :-/
<namespace name="RS.Practice.UnityLoggingExample.CommonInterfaces" />
<assembly name="RS.Practice.UnityLoggingExample.CommonInterfaces" />
<namespace name="RS.Practice.UnityLoggingExample.LoggingLibrary1" />
<assembly name="RS.Practice.UnityLoggingExample.LoggingLibrary1" />
<!-- CONTAINERS -->
<register type="ILogger" mapTo="CustomLogger1">
<lifetime type="singleton" />
It always complains about CustomLogger1 not being there. It is part of LoggingLibrary1.
Do I still misunderstand the concept or am I doing it wrong?
Nevermind. I didn't have the assembly in the debug directory :-/
Is it possible to reference assemblies using their fully qualified name? With version, culture and public key token?