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);
}
}
}