Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unity and dependence on collection of objects

In my case some class depends not on a single object, but on collection of them:

public class ImportController { ...
public ImportController(IEnumerable<IImportManager> managers) { ... }
}

public class ProductAImportManager : IImportManager { ... }
public class ProductBImportManager : IImportManager { ... }
public class ProductCImportManager : IImportManager { ... }

I want to instantiate ImportController using Unity, so how should I register the dependencies?

If I use something like

unityContainer.RegisterType<IImportManager, ProductAImportManager>();
unityContainer.RegisterType<IImportManager, ProductBImportManager>();

second call just overrides the first one.

Is there any way to ask Unity to find all types registered that implements IImportManager interface, instantiate these types and pass the sequence of objects to my constructor?

like image 332
AndreyTS Avatar asked Mar 22 '11 07:03

AndreyTS


2 Answers

Unity has somewhat bizarre resolution rules when it comes to multiple registrations.

  • Registrations made without a name (i.e. container.RegisterType<IInterface, Implementation>()) can only be resolved with container.Resolve.

  • Registrations made with a name can only be resolved with container.ResolveAll<IInterface>().

The trick I use to depend on a collection of registrations is a two line method that calls ResolveAll behind the scenes:

public static class UnityExtensions {  
   public static void RegisterCollection<T>(this IUnityContainer container) where T : class {
    container.RegisterType<IEnumerable<T>>(new InjectionFactory(c=>c.ResolveAll<T>()));
  }
}

Usage is simple from here on in.

//First register individual types
unityContainer.RegisterType<IImportManager, ProductAImportManager>("productA");
unityContainer.RegisterType<IImportManager, ProductBImportManager>("productB");
//Register collection
unityContainer.RegisterCollection<IImportManager>();
//Once collection is registered, IEnumerable<IImportManager>() will be resolved as a dependency:
public class ImportController { ...
  public ImportController(IEnumerable<IImportManager> managers) { ... }
}
like image 117
Igor Zevaka Avatar answered Oct 31 '22 22:10

Igor Zevaka


You can, with named types and arrays:

unityContainer.RegisterType<IImportManager, ProductAImportManager>("a");
unityContainer.RegisterType<IImportManager, ProductBImportManager>("b");


public class ImportController { ...
   public ImportController(IImportManager[] managers) { ... }
}
like image 3
onof Avatar answered Oct 31 '22 22:10

onof