Проблема в том, что лямбда m => m.DoSomething()
равна , а не так же, как DoSomething
.Это лямбда-выражение, которое компилируется в вызов метода для сгенерированного компилятором метода, возможно, с использованием сгенерированного компилятором типа (хотя, возможно, не последнего, поскольку нет захваченных локальных переменных).
Оченьподробный способ получения Action<Foo>
из экземпляра (нестатического) метода типа Foo
таков:
var myAction = (Action<Foo>)Delegate.CreateDelegate(
typeof(Action<Foo>),
null, // treat method as static, even though it's not
typeof(Foo).GetMethod("DoSomething", BindingFlags.Instance | BindingFlags.Public)
);
Очевидно, что это далеко от идеала и, вероятно, на самом деле бесполезно в вашем случае;но это стоит знать;)
Обновление : На самом деле, мне пришло в голову, что вы можете написать быстрый метод расширения, чтобы сделать это простым для любого экземпляраметод, который вы хотите обернуть как статический метод (и поддерживать «правильный» MethodInfo
):
public static class ActionEx
{
public static Action<T> ToStaticMethod<T>(this Action action)
{
if (!(action.Target is T))
{
throw new ArgumentException("Blah blah blah.");
}
return (Action<T>)Delegate.CreateDelegate(
typeof(Action<T>),
null,
action.Method
);
}
}
Это позволит вам сделать:
Action<Foo> myAction = new Action(new Foo().DoSomething).ToStaticMethod<Foo>();
По общему признанию, этоне так хорошо, как m => m.DoSomething()
;но он действительно дает вам Action<T>
, свойство Method
которого фактически ссылается на метод DoSomething
напрямую.
В качестве альтернативы, вместо Action<T>
, вы можете использоватьExpression<Action<T>>
и получите MethodInfo
от этого.Обратите внимание, что синтаксис в этом случае выглядит одинаково:
Action<Foo> myAction = m => m.DoSomething();
Expression<Action<Foo>> myExpression = m => m.DoSomething();
Но это сложное предложение, поскольку произвольный Expression<Action<T>>
не гарантированно будет таким простым, как просто m => m.DoSomething()
.