I’m working on a small project that uses Unity to manage record type-specific data providers. As a brief overview, the project accepts a collection of objects. An appropriate data provider is retrieved for each object, and then the object is passed to that provider for processing.
I register the providers in a UnityContainer like so:
UnityContainer.RegisterType<IDataProvider<RecordType>, RecordTypeDataProvider>();
So, in a perfect world, I wanted to resolve the providers based on the type of each record in a collection. Something like this:
foreach (var record in collection) { var provider = ResolveProvider(record); provider.Process(record); }
The problem with this approach is that I need to resolve the type using the record’s type.
// what I want (invalid) UnityContainer.Resolve<IDataProvider<record.GetType()>>();
Luckily, there’s a way to do this by using the Type.MakeGenericType method. Check it out:
var providerType = typeof(IDataProvider<>).MakeGenericType(record.GetType()); var provider = UnityContainer.Resolve(providerType);
This works, but it leaves me with another challenge. UnityContainer.Resolve returns an object, but I need an IDataProvider. The solution? A base interface containing the non-generic methods and properties. This allows me to resolve the data provider using the record type but still return a typed object. Here’s the complete solution:
public interface IDataProvider { void Process(BaseType record); } public interface IDataProvider<T> : IDataProvider where T : BaseType { void Process<T>(T record); } public class RecordTypeDataProvider : IDataProvider<RecordType> { // IDataProvider.Process public void Process(BaseType record) { Process(record as RecordType); } // IDataProvider<RecordType>.Process public void Process<RecordType>(RecordType record) { // process it! } } public static class Broker { private static readonly UnityContainer UnityContainer; static Broker() { UnityContainer = new UnityContainer(); UnityContainer.RegisterType<IDataProvider<RecordType>, RecordTypeDataProvider>(); // other providers... } private static IDataProvider Resolve(BaseType record) { var providerType = typeof(IDataProvider<>).MakeGenericType(record.GetType()); return UnityContainer.Resolve(providerType) as IDataProvider; } public static void Process(IEnumerable<BaseType> collection) { foreach (var record in collection) { var provider = Resolve(record); provider.Process(record); } } }