[英]Invoking C# Delegate Method when delegate is passed as Generic Argument
我在防止重复代码时遇到麻烦。
目前,我有以下方法:
protected delegate bool CallbackDelegate<T>(T param, out string result);
protected delegate bool CallbackDelegate<T, U>(T param1, U param2, out string result);
protected bool ClientCtrlCallback<T>(T param, CallbackDelegate<T> callbackMethod)
{...}
protected bool ClientCtrlCallback<T,U>(T param1, U param2, CallbackDelegate<T,U> callbackMethod)
{...}
这两个ClientCtrlCallback方法具有相同的代码(检查通信通道的有效性,try-catch块,获取锁等),该代码围绕对CallbackDelegate方法的调用而构建。
我一直在尝试合并这些ClientCtrl方法,但未成功,因为不允许委托约束。 据我所知:(为清楚起见,删除了不必要的代码)
protected delegate bool CallbackDelegate1<T>(T param, out string result);
protected delegate bool CallbackDelegate2<T, U>(T param1, U param2, out string result);
protected const string METHOD_MY_DELEGATE1 = "CallbackDelegate1";
protected const string METHOD_MY_DELEGATE2 = "CallbackDelegate2";
protected interface ParameterSet { };
protected class OneParameter<T>: ParameterSet { public T p1; };
protected class TwoParameters<T,U> : ParameterSet { public T p1; public U p2; };
protected bool ClientCtrlCallback<D,T,U>(ParameterSet parameterset, D callbackMethod, string successLog = null) // where MyDelegate : delegate //not allowed
{
// delegate constrained is not allowed, so check it here
if (!typeof(D).IsSubclassOf(typeof(Delegate)))
return false;
// check name of method (this works)
string methodName = (callbackMethod as Delegate).Method.Name;
// Call the delegate // doesn't work.
string result;
switch (methodName)
{
case METHOD_MY_DELEGATE1:
// doesnt work
//(callbackMethod as Delegate)((parameterset as OneParameter<T>).p1, out result);
break;
case METHOD_MY_DELEGATE2:
// doesnt work
//(callbackMethod as Delegate)((parameterset as TwoParameters<T, U>).p1, (parameterset as TwoParameters<T, U>).p2, out result); // doesnt work
break;
}
return true;
}
参数类开始变得丑陋。 切换比较代表姓名的情况变得更糟(我也不希望每个人都给他们起一个不同的名字)。 然后,当我想调用委托的方法时,总会遇到麻烦:编译时错误Method name expected
我不明白为什么我可以从Delegate获得方法名称,却不能调用Delegate的方法。 我错过了什么大事吗?
不要让此方法负责首先接受将传递给回调的参数。 不要传入任何参数。 如果调用方具有要在回调中使用的值,则可以使用闭包关闭该变量。
这个对象不仅很难接受任意数量的参数并将其传递给回调(并且不可能以类型安全的方式完全泛化),而且对于调用者来说,在一个完全通用的情况下解决此问题也非常容易完全安全的方式,但从逻辑上讲,该信息是调用方的私有实现细节,而不是此方法首先有任何理由要了解的信息。
已编辑
您不能只拥有:
protected delegate bool CallbackDelegate<TParameterSet>(TParameterSet param, out string result)
where TParameterSet : ParameterSet;
然后(根据您其余的代码,现在似乎没什么用):
protected bool ClientCtrlCallback<TParameterSet>(TParameterSet parameterset, CallbackDelegate<TParameterSet> callbackMethod, string successLog = null)
where TParameterSet : ParameterSet
{
string result;
return callbackMethod(parameterset, out result);
}
最后是您的回调方法:
bool CallbackMethodOneParameter<T>(OneParameter<T> parameter, out string result)
{
// Do your stuff with parameter.p1;
// set result
// return success or fail
}
bool CallbackMethodTwoParameters<T, U>(TwoParameters<T, U> parameters, out string result)
{
// Do your stuff with parameters.p1 and parameters.p2;
// set result
// return success or fail
}
不再申请
我也想知道您是否真的需要在这里使用泛型。 您的回调方法可能已经知道ParameterSet包含哪些类型。
因为使用此泛型,如果您需要另一个参数,则必须在此签名处的任何地方进行更改。 它会变得痛苦。
在代码中,要调用您的委托,您可以执行以下操作:
var parameters = new object[] { (parameterset as OneParameter<T>).p1, null };
var success = (callbackMethod as Delegate).DynamicInvoke(parameters);
result = parameters[1];
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.