It was done this way so that you can have a Composite.
An example Composite IService
public class CompositeDataService : IService
{
public readonly IService[] services;
public CompositeDataService(IService[] services)
{
this.services = services;
}
}
And a demonstration test
[Fact]
public void Test()
{
var container = new UnityContainer();
container.RegisterType<IService, CompositeDataService>();
container.RegisterType<IService, LoggingService>("Logging");
container.RegisterType<IService, CachingService>("Caching");
var service = container.Resolve<IService>();
Assert.IsType<CompositeDataService>(service);
Assert.Equal(2, ((CompositeDataService)service).services.Count());
}
It is officially documented here
The two overloads of this method [ResolveAll
] accept either an interface or a type name, and they return an instance of IEnumerable
that contains references to all registered objects of that type that are not default mappings. The list returned by the ResolveAll
method contains only named instance registrations. The ResolveAll
method is useful if you have registered multiple object or interface types using the same type but different names
Here is some code to work around it (Note: I haven't run the code)
using System;
using Microsoft.Practices.ObjectBuilder2;
using Microsoft.Practices.Unity;
public class Remember : UnityContainerExtension
{
protected override void Initialize()
{
this.Context.Registering += this.OnRegistering;
this.Context.RegisteringInstance += this.OnRegisteringInstance;
}
private void OnRegisteringInstance(object sender, RegisterInstanceEventArgs e)
{
if(string.IsNullOrEmpty(e.Name))
{
string uniqueName = Guid.NewGuid().ToString();
this.Context.RegisterNamedType(e.RegisteredType, uniqueName);
this.Context.Policies.Set<IBuildKeyMappingPolicy>(
new BuildKeyMappingPolicy(new NamedTypeBuildKey(e.RegisteredType)),
new NamedTypeBuildKey(e.RegisteredType, uniqueName));
}
}
private void OnRegistering(object sender, RegisterEventArgs e)
{
if (e.TypeFrom != null && string.IsNullOrEmpty(e.Name))
{
string uniqueName = Guid.NewGuid().ToString();
this.Context.RegisterNamedType(e.TypeFrom, uniqueName);
if (e.TypeFrom.IsGenericTypeDefinition && e.TypeTo.IsGenericTypeDefinition)
{
this.Context.Policies.Set<IBuildKeyMappingPolicy>(
new GenericTypeBuildKeyMappingPolicy(new NamedTypeBuildKey(e.TypeTo)),
new NamedTypeBuildKey(e.TypeFrom, uniqueName));
}
else
{
this.Context.Policies.Set<IBuildKeyMappingPolicy>(
new BuildKeyMappingPolicy(new NamedTypeBuildKey(e.TypeTo)),
new NamedTypeBuildKey(e.TypeFrom, uniqueName));
}
}
}
}
With an example
[TestMethod]
public void CanResolveMultipeDefaultMappingsUsingResolveAll()
{
var container = new UnityContainer().AddNewExtension<Remember>();
container.RegisterType<IFoo, One>();
container.RegisterType<IFoo, Two>();
container.RegisterType<IFoo, Three>();
IFoo[] foos = container.ResolveAll<IFoo>().OrderBy(f => f.GetType().Name).ToArray();
Assert.AreEqual(3, foos.Length);
Assert.IsInstanceOfType(foos[0], typeof(One));
Assert.IsInstanceOfType(foos[1], typeof(Three));
Assert.IsInstanceOfType(foos[2], typeof(Two));
}