Func委托的更好(通用)声明

时间:2012-02-23 00:34:09

标签: c# .net generics reflection func

好的,我希望这个问题的标题是有道理的。在我的应用程序中,我有一些方法应该由特殊的InvokeMethod调用。目前,它的工作原理如下:

internal bool RemoteLogin(string password)
{
    return (bool)InvokeMethod(new Func<string, bool>(Server.RemoteLogin), password);            
}

internal string GetSessionId()
{            
    return (string)InvokeMethod(new Func<string>(Server.GetSessionId));                      
}

public object InvokeMethod(Delegate method, params object[] args)
{
    return method.DynamicInvoke(args);
}    

要调用InvokeMethod,我必须传递一个新的Func&lt; ....&gt ;,添加参数,并将返回值强制转换为适当的类型。是否有更好的(更通用的)方法,例如使用Generics或Reflection?

非常感谢任何帮助。

5 个答案:

答案 0 :(得分:3)

您可以使用Func变体来实现一定程度的强打字 - 以牺牲重复为代价:

public R InvokeMethod<T,R>(Func<T,R> method, T argument)
{
    return method(argument);
}   

public R InvokeMethod<T1,T2,R>(Func<T1,T2,R> method, T1 argument1, T2 argument2)
{
    return method(argument1, argument2);
}   

public R InvokeMethod<T1,T2,T3,R>(Func<T1,T2,T3,R> method, T1 argument1, T2 argument2, T3 argument3)
{
    return method(argument1, argument2, argument3);
}   

等等。

虽然这与您的原始版本一致,但根本不需要处理参数。尝试用这种方式写InvokeMethod

public R InvokeMethod<R>(Func<R> method)
{
    return method();
}

然后用这种风格调用它:

internal bool RemoteLogin(string password)
{
    return InvokeMethod(() => Server.RemoteLogin(password));
}

internal string GetSessionId()
{            
    return InvokeMethod( () => Server.GetSessionId());
}

这样,您就可以将参数处理留给lambda表达式,只需要编写一次InvokeMethod。

答案 1 :(得分:2)

“在上面的例子中,方法InvokeMethod被简化了。在我的应用程序中,它会对调用进行日志,监视,异常处理等。”

鉴于此评论,我的建议是重做这一点。您可以将操作设为Func<T>,而不是像这样调用委托:

public T InvokeMethod<T>(Func<T> method)
{
    // Add wrapper as needed
    return method();
}

然后,当您需要传递参数时,可以使用lambdas调用它:

internal bool RemoteLogin(string password)
{
    return InvokeMethod(() => Server.RemoteLogin(password));            
}

internal string GetSessionId()
{            
    return InvokeMethod(Server.GetSessionId);                      
}

答案 2 :(得分:1)

我同意Reed你真的可以直接调用这个方法并消除一些冗余代码,但如果你在做这些事情时想要那么强大的输入,那么很容易重写InvokeMethod这样的调用

public static T InvokeMethod<T>(Delegate method, params object[] args)
{
    return (T)method.DynamicInvoke(args);
} 

然后你上面的电话就变成了:

return InvokeMethod(new Func<string, bool>(Server.RemoteLogin), password);  

Boolean返回类型由方法的返回类型推断。

答案 3 :(得分:1)

static T Invoke<T>(Func<T> method)
{
  //Log here
  return method();
}

bool RemoteLogin(string password)
{
  return Invoke(() => Server.RemoteLogin(password));
}

答案 4 :(得分:1)

附加信息:如果方法没有返回值(例如“void Logout()”),您可以使用Action委托(方法可以具有相同的名称 - &gt; InvokeMethod - &gt;因为签名/参数不同) :

public void InvokeMethod(Action method)
{
    method();
}