Everybody seems to be using some form of Dependency Injection nowadays. Most of common reasons have been in regards to testability, modularizing and reach a greater sense of "loose coupling".
In most cases Dependency Injection introduces another level of complexity as the available frameworks require some code changes before you can actually utilize DI.
A forgotten "Trade-Secret"?
One of the .NET "Trade-Secrets" I wanted bring forward as a potential alternative to DI is Assembly Redirection. This is a technique which is part of the core concept of the .NET Framework from the early beginning. The idea is that a you can redirect an assembly load request to a different assembly (file) than was originally referenced in your program.
For example, a console application called MyTest.exe has a reference to MyMain.dll. Say that MyMain.dll is a wrapper around a legacy API but now we want to utilize a new API. With Assembly Redirection we could create a new dll which implements the same methods as the previous one and have it replace the old dll by just changing the MyTest.exe.config file. You wouldn't even have to recompile the console app.
Sample Project
I have created a sample solution which you can use to experiment yourself and to follow this article. For the purpose of this sample, just pretend that we are trying to introduce the ability to swap logging libraries.
The solution consists of one console application, and four class libraries.
The AssemblyRedirectionSample Project
The AssemblyRedirectionSample project is our test console which uses the GenericImplementation project for logging purposes.
The Common Project
The common project contains one close with the Interface definition which is not required for AR to work but it makes it easier for the demo to create the various implementations.
The GenericImplemtation Project
In this sample we just assume that we do logging through a known and common approach. The GenericImplementation project is our representation of that common approach for demo purposes.
The NLogImplementation and the EABImplementation Projects
Those two project represent the change in logging library use over time. Each project implements the interaction with the associated logging library.
AR Requirements
To be able to utilize the AR technique you need to keep the following things in mind: 
- Namespace: The namespace in the replacing implementation needs to be the same as the original one,
- Class: The classes defined in the original implementation need to be available in the replacing implementation,
- Methods, Properties, Types: Anything defined in the original implementation must exist in the replacing one, however it is possible to introduce new types, methods, properties and such but your "legacy" code wouldn't know about it,
- Assembly Name: the assembly must be name exactly like the original one, the Assembly name is used as the Identifier during the assembly load process to locate the assembly (dll). In the picture on the right, properties of the reference, you can see Identity attribute being set to "Implementation", this is the key element we need later in the configuration of AR,
- File name: The file name of the replacing implementation is not important and could be named anything,
- File location: The file location of the replacing implementation is not important as long as the host application has access to the folder,
When you select the GenericImplementation reference in the console application, take a look at the properties of the references as shown in the image on the right. In the properties page you will see the Identity attribute, in this sample it is set to "Implementation".
The Identity attribute of the reference is actually the Assembly Name as set on the GenericImplementation project. You can find the the Assembly name on the Application tab of the Properties page of the project, as shown on the right. If you change the Application name you will see the Identity attribute changing after a build.
By changing the assembly name you also change the file name which is controlled by the same field.
The Code
The console application (AssemblyRedirectionSample) has a reference to the "GenericImplementation" project as shown in the solution structure image above.
The code snippet below is the Main method of the console application, as you can see on line 8 we are just instantiating the Logger as defined in the GenericImplementation project. There is no real magic here...
1: static void Main(string[] args)
2: {
3: Console.Write("Press Enter to Start: ");
4: Console.ReadLine();
5:
6: try
8: ILogger logger = new Logger();
9:
10: logger.Trace("Some message here");
11: }
12: catch (Exception ex)
13: {
14: Console.WriteLine(ex.Message);
15: }
16: Console.ReadLine();
17: }
A new implementation
Now that time has gone by, we want to replace the generic implementation to for example the NLog approach. This is now a fairly simple thing to do you need to keep the AR Requirements list in mind.
The NLogImplementation is a different implementing of the ILogger interface. If you make sure you have all the AR requirements covered you should have something similar to the original implementation. Take a look at the NLogImplementation in sample solution, look at the project properties page and verify that the Assembly name is identical to the Assembly name of the GenericImplementation project.
Running the Sample and Redirecting
When you run the console application you will see the output coming from the generic implementation. Now comes the fun part, open up the RedirectionTest.exe.config inside the console application. The RedirectionTest.exe.config is displayed below.
1: <?xml version="1.0" encoding="utf-8" ?>
2: <configuration>
3: <runtime>
4: <!--
5: <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
6: <dependentAssembly>
7: <assemblyIdentity name="Implementation" />
8:
9: <codeBase href="bin/NLogImplementation/Implementation.dll"/>
10: <codeBase href="bin/EABImplementation/Implementation.dll"/>
11:
12: </dependentAssembly>
13: </assemblyBinding>
14: -->
15: </runtime>
16: </configuration>
The assembly redirection is based on the assemblyBinding and the assemblyIdentity elements within the runtime node.
The assemblyBinding element is one part of dealing with assembly redirection. You can read about the specifics here.
The dependentAssembly has no attributes and encapsulates binding policy and assembly location for each assembly. Use one dependentAssembly element for each assembly.
The assemblyIdentity element is used to identify the assembly you want to redirect. There are other attributes you can use such as culture, publicKeyToken and proccessorArchitecture but those are optional. You can read about the assemblyIdentity element here.
One of the methods of assembly redirection is to use the codeBase elements, this element basically indicates the location where the CLR can find the assembly. There is also use the bindingRedirect element which does the redirection based on version numbering, read all about it here. This element is outside the scope of this sample.
In the sample I am using the codeBase element which specifies where the CLR can find the assembly. The documentation specifies that both the href and the version attribute on the element are required. As you can see from the sample above the version attribute is not present. Reading the remarks in the documentation specifies that if the assembly is not strongly named you wouldn't need it.
If you un-comment the assemblyBinding piece, save the file and then run the executable you would see that the message now comes from the NLog implementation. If you comment out the NLog codeBase element, save the file and run the executable you will see the message from the EAB implementation.
Summary
What I tried to show is that there is an out-of-the-box way of introducing new code in existing applications based on Assembly Redirection. This method might be a viable solution in places where you need to use mocking for testing purposes or in places where you would want to switch implementations. There may be other scenarios but I leave that up to your imagination.
AssemblyRedirectionSample.zip (89.62 kb)