繁体   English   中英

当委托作为通用参数传递时调用C#委托方法

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM