Trying to register a generic instance creator

Jun 16, 2014 at 9:10 PM
Edited Jun 16, 2014 at 10:55 PM
Given something like:
    MongoCollection<T> GetCollection<T>()
    {
        return db.GetCollection<T>();
    }
I would like to do something like this:
    container.Register<T>(typeof(MongoCollection<>), GetCollection<T>);
    //or
    container.Register<T>(typeof(MongoCollection<>), () => GetCollection<T>());
Of course I know this is far from compiling, but is something along these lines possible?
Coordinator
Jun 16, 2014 at 9:32 PM
Typically you would do this using the RegisterOpenGeneric extension method, but this method only supports types, not methods. To do this you should either create a derivative of MongoCollection<T> and let this call db.GetCollection<T> under the covers (if possible), or you will need to fallback to hooking onto the ResolveUnregisteredType event (which is what RegisterOpenGeneric does under the covers).

If you go with the latter, it might look like this:
container.ResolveUnregisteredType += (s, e) =>
{
    Type type = e.UnregisteredServiceType;
    if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(MongoCollection<>))
    {
        Type elementType = type.GetGenericArguments()[0];
        // Get the right method with the proper generic type filled in
        var method = this.GetType().GetMethod("GetCollection").MakeGenericMethod(elementType);
        // Register an expression that calls this method.
        e.Register(Expression.Call(Expression.Constant(this), method));     
    }
};
Jun 16, 2014 at 10:54 PM
Awesome. Thanks for the prompt response.