通过字符串将方法名称分配给Func

时间:2012-09-25 22:23:52

标签: c# asp.net c#-4.0

基本上我想这样做:

Func<string> f =  ()=> MyMethodName();

只有一个方法的字符串名称,即:

 Func<string> f =  "MyMethodName";

可以这样做吗?任何问题,警告?反思有帮助吗?我可以先检查方法是否存在吗?

3 个答案:

答案 0 :(得分:6)

这里根本不需要lambda表达式。您可以使用Delegate.CreateDelegate

MethodInfo method = GetType().GetMethod(methodName);
Func<string> func = (Func<string>) Delegate.CreateDelegate(typeof(Func<string>),
                                                           obj, method);

这样你可以避免间接级别,并且你也可以在中执行反射部分而不是每次调用。

答案 1 :(得分:2)

以下是反思的例子:

Func<string> func = ( ) => {
    return ( string )( this.GetType( ).GetMethod( "MyMethodName" ).Invoke( this, new object[ 0 ] ) );
}

如果你想要一些东西来缓解这件事,那就是:

public static Func<string> ReflectByName( object obj, string methodname ) {
    return ( ) => {
        return ( string )( obj.GetType( ).GetMethod( methodname ).Invoke( obj, new object[ 0 ] ) );
    }
}

使用方法:

Func<string> f = FastReflect.ReflectByName( this, "MyMethodName" );

FastReflect方法ReflectByName所在的位置。

答案 2 :(得分:0)

这是另一种方法。这样做的优点是比反射快得多,所以如果需要在循环中调用它,那就太好了。此代码创建一个将调用方法

的Func
    public static Func<T, string> CreateCallFunc<T>(string methodName)
    {
        var parm = Expression.Parameter(typeof(T));
        var call = Expression.Call(parm, typeof(T).GetMethod(methodName));
        var lambda = Expression.Lambda<Func<T, string>>(call, parm);
        return (Func<T, string>)lambda.Compile();
    }

你这样使用它:

    class SomeClass
    {
        void DoIt()
        {
            var func = CreateCallFunc<SomeClass>("SomeMethod");
            Console.WriteLine(func(this));
        }

        public string SomeMethod()
        {
            return "it works!";
        }
    }

最大的好处是,一旦你创建了你的Func,你只需使用func(myInstance)就可以非常简单地调用它,它会非常快。

我使用此方法获取DataReader并将读取中的所有数据复制到类的集合中,其中类的属性名称与读取器中的字段匹配。

请注意,约翰的答案是一种更容易实现的方法,直到现在我才知道这一点,但我认为这具有更大的灵活性