开发者

How to activate a generic method that takes an action as its parameter

How would you go about using reflection to execute the following method when the type can only be inferred at runtime?

MainObject.TheMethod<T>(Action<OtherObject<T>>)

in everyday use, typically:

mainObject.Method<Message>(m => m.Do("Something"))

So, given a list of types, I need to substitute them for T in the method above and invoke.

This is where I got before my head to turned to putty:

var mapped = typeof(Action<OtherObject<>>).MakeGenericType(t.GetType());
Activator.CreateInstance(mapped,  new object[] { erm do something?});

typeof(OtherObject)
    .GetMethod("TheMethod")
    .MakeGenericMethod(t.GetType())
    .Invoke(model, new object[] { new mapped(m => m.Do("Something")) });

Update: For clarification, i have a list of types and i wish to execute the same known method of OtherO开发者_StackOverflow社区bject for each. Pseudo-code:

foreach(var t in types)
{
    mainObject.TheMethod<t>(mo => mo.Do("Something"))
}

(The type of the parameter for TheMethod() is Action<OtherObject<T>> as stated above)

FluentNHibernate.Automapping.AutoPersistenceModel Override<T>(System.Action<AutoMapping<T>> populateMap)

the action is the same of AutoMapping<T>.Where("something")

model.Override<Message>(m => m.Where("DeletedById is null"))

Now, do that for a bunch of types :)


You can solve this by using expressions:

foreach(var t in types)
{
    var mapped = typeof(AutoMapping<>).MakeGenericType(t);

    var p = Expression.Parameter(mapped, "m");
    var expression = Expression.Lambda(Expression.GetActionType(mapped),
                                       Expression.Call(p, mapped.GetMethod("Do"),
                                       Expression.Constant("Something")), p);

    typeof(SomeOtherObject).GetMethod("TheMethod").MakeGenericMethod(t)
                           .Invoke(model, new object[] { expression.Compile() });
}

UPDATE: Complete working example (paste into LINQPad and run it):

void Main()
{
    var types = new []{typeof(string), typeof(Guid)};
    SomeOtherObject model = new SomeOtherObject();
    foreach(var t in types)
    {
        var mapped = typeof(AutoMapping<>).MakeGenericType(t);

        var p = Expression.Parameter(mapped, "m");
        var expression = Expression.Lambda(
                             Expression.GetActionType(mapped),
                             Expression.Call(p, mapped.GetMethod("Do"),
                             Expression.Constant("Something")), p);

        typeof(SomeOtherObject).GetMethod("TheMethod")
                               .MakeGenericMethod(t)
                               .Invoke(model,
                                       new object[] { expression.Compile() });
    }
}

class AutoMapping<T>
{
    public void Do(string p)
    {
        Console.WriteLine(typeof(T).ToString());
        Console.WriteLine(p);
    }
}

class SomeOtherObject
{
    public void TheMethod<T>(Action<AutoMapping<T>> action)
    {
        var x = new AutoMapping<T>();
        action(x);
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜