I have a use case where my company moves from a legacy codebase to a new legacy codebase. The combination is unstable, merging the containers would help.
I identified a point where I want to merge the containers and pass a new container to the remaining application.
I have reason to believe that I can overwrite old types without causing problems.
How can I merge an IUnityContainer
with another IUnityContainer
?
The following is how far my experiments have taken me:
using Microsoft.Practices.Unity;
using System;
using System.Collections.Generic;
using System.Linq;
class ContainerUser
{
public ContainerUser(IEnumerable<IUnityContainer> chaos)
{
IUnityContainer combined = new UnityContainer();
//is there a highlevel method that can be used?
//or is a foreach loop the way to go
foreach (var uc in chaos)
{
foreach (var reg in uc.Registrations)
{
//combined.Register...???
//usure what to so here
}
}
//this throws unless combining the conainers works
combined.Resolve<L1>().Exec();
combined.Resolve<L2>().Exec();
}
}
class L1
{
private L1() { } //private so UnityContainer can not default construct
public static L1 Get() { return new L1(); } //getter for InjectionFactory
public void Exec() { Console.WriteLine("L1"); }
}
class L2
{
private L2() { }
public static L2 Get() { return new L2(); }
public void Exec() { Console.WriteLine("L2"); }
}
class Program
{
public static IEnumerable<T> Randomize<T>(IEnumerable<T> source)
{
//randomize to show i do not know a lot about my different containers
Random rnd = new Random();
return source.OrderBy<T, int>((item) => rnd.Next());
}
static void Main(string[] args)
{
//this is the setup, in my usecase these things happe behind the scenes and i can not influence them.
var ucs = new List<IUnityContainer> { new UnityContainer(), new UnityContainer() };
ucs[0].RegisterType<L1>(new InjectionFactory(c => L1.Get()));
ucs[0].Resolve<L1>().Exec(); //proof L1 can resolve
ucs[1].RegisterType<L2>(new InjectionFactory(c => L2.Get()));
ucs[1].Resolve<L2>().Exec(); //proof L2 can resolve
ContainerUser user = new ContainerUser(Randomize(ucs));
}
}
This is a simple approach how to use extensions to merge containers:
public class MergeContainerExtension : UnityContainerExtension
{
private readonly IUnityContainer[] containers;
public MergeContainerExtension(params IUnityContainer[] containers)
{
this.containers = containers;
}
protected override void Initialize()
{
foreach (var container in containers)
{
foreach (var registration in container.Registrations)
{
base.Container.
RegisterType(
registration.RegisteredType,
registration.MappedToType,
registration.Name,
registration.LifetimeManager);
}
}
}
}
class Program
{
static void Main(string[] args)
{
UnityContainer aContainer = new UnityContainer();
UnityContainer bContainer = new UnityContainer();
UnityContainer container = new UnityContainer();
MergeContainerExtension mergeExtension = new MergeContainerExtension(aContainer, bContainer);
container.AddExtension(mergeExtension);
var resolve = container.Resolve<IClassA>();
}
}