Подтвердить что ты не робот

Как активировать общий метод, который принимает действие в качестве параметра

Как вы могли бы использовать отражение для выполнения следующего метода, когда тип может быть выведен только во время выполнения?

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

в повседневном использовании, обычно:

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

Итак, учитывая список типов, мне нужно подставить их для T в вышеописанном методе и вызвать.

Вот где я добрался до головы, чтобы обратиться к шпатлевке:

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

Обновление: Для уточнения, у меня есть список типов, и я хочу выполнить один и тот же известный метод для другого объекта для каждого. Псевдо-код:

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

(Тип параметра для метода TheMethod() равен Action<OtherObject<T>>, как указано выше)

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

одно и то же действие AutoMapping<T>.Where("something")

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

Теперь сделайте это для нескольких типов:)

4b9b3361

Ответ 1

Вы можете решить это, используя выражения:

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: полный рабочий пример (вставьте в LINQPad и запустите его):

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