当委托作为泛型参数传递时调用c#委托方法
本文关键字:调用 方法 泛型 参数传递 | 更新日期: 2023-09-27 18:09:57
我在防止重复代码方面遇到了麻烦。
目前我有这些方法:
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
我不明白为什么我可以从委托中获得方法名,但不能调用委托的方法。我是不是错过了什么大事?
不要让这个方法负责接受将首先传递到回调中的参数。不要传入任何参数。如果调用者有一个值,他们想在回调中使用,那么可以使用闭包来关闭该变量。
不仅是极其困难的这个对象接受任意数量的参数,并将它们传递到回调(并无法完全概括类型安全的方式),也非常简单的调用者来解决这个问题的一个完全一般情况并完全类型安全的方式,但这信息是逻辑上私人调用程序的实现细节,而不是信息,这种方法有任何理由在第一时间知道。
EDITED
你就不能有:
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];