Creating Generic Type Instances Created Using Reflection

I create instances of the generic type using reflection:

public interface IModelBuilder<TModel>
{
    TModel BuildModel();
}

public class MyModel
{
    public string Name { get; set; }
}

public class MyModelBuilder : IModelBuilder<MyModel>
{
    public MyModel BuildModel()
    {
        throw new NotImplementedException();
    }
}

At run time, all we know is Model Type, for example. MyModel. I can find instances of the corresponding model builder as follows:

var modelBuilders = from t in Assembly.GetExecutingAssembly().GetTypes()
                from i in t.GetInterfaces()
                where i.IsGenericType
                        && i.GetGenericTypeDefinition() == typeof(IModelBuilder<>)
                        && i.GetGenericArguments()[0] == modelType
                select t;

var builder = Activator.CreateInstance(modelBuilders.First());

But I'm not sure how I can then cast the instance as IModelBuilder<TModel>so that I can call and work with the result BuildModel().

+5
source share
1 answer

Since it modelTypeis just an instance Type, you cannot do this automatically, since there is no universal API. Various options:

1: use reflection, for example (untested)

object builder = Activator.CreateInstance(...);
var model=builder.GetType().GetMethod("BuildModel").Invoke(builder,null);

2: trick using dynamic:

dynamic builder = Activator.CreateInstance(...);
var model = builder.BuildModel();

3: IModelBuilder

, 1 2 ( ) . "1" :

var model = typeof(IModelBuilder<>).MakeGenericType(modelType)
       .GetMethod("BuildModel").Invoke(builder);

- , . dynamic:

interface ISneaky<T>
{
    T Foo { get; }
}
class Sneaky<T> : ISneaky<T>
{
    T ISneaky<T>.Foo { get { return default(T); } }
}
class Program
{
    static void Main()
    {
        Execute(typeof(int));
    }
    static void Execute(Type t)
    {
        dynamic obj = Activator.CreateInstance(
            typeof(Sneaky<>).MakeGenericType(t));
        // crafy hack to flip from non-generic code into generic code:
        Evil(obj);
    }
    static void Evil<T>(ISneaky<T> sneaky)
    {   // in here, life is simple; no more reflection
        Console.WriteLine("{0}: {1}", typeof(T).Name, sneaky.Foo);
    }
}
+14

All Articles