一个一个地向委托添加参数然后执行它
Add arguments one by one to a delegate then execute it
昨天我想创建一个 ExceptionHandler
class 例如我们可以传递给它:
- 异常
- 发生这种情况的方法
- 给该方法的参数
ExceptionHandler
将实现自定义业务逻辑并自动(或不)重新执行具有相同参数的方法。
The closest solution I found 是通过使用 delegate
这样的
private void button1_Click(object sender, EventArgs e)
{
InvokeMyMethod(Test, "string", 1);
InvokeMyMethod(TestN, "other string", 3, Color.Red);
}
public delegate void MyMethodDelegate(params object[] args);
public void InvokeMyMethod(MyMethodDelegate method, params object[] args)
{
method.DynamicInvoke(args);
}
public void Test(params object[] args)
{
if (args.Length < 2) return;
MessageBox.Show(string.Format("{0}{1}", args[0], args[1]));
}
public void TestN(params object[] args)
{
// or, whatewer
if (args.Length < 3) return;
MessageBox.Show(string.Format("{0}{1}{2}", args[0], args[1], args[2]));
}
然而,由于方法的签名,这个解决方案仍然不完美。我不希望我的所有方法都接收一个唯一参数 params object[] args
,而且这通常不可能直接实现,例如对于所有 UI 相关事件(Winform、ASP.NET、WPF 或其他)。
所以我想知道是否有一种方法可以将参数一个一个地传递给委托,然后仅在我们准备好时才执行该函数?
例如,这里是一个虚构的代码,其中包含不存在的方法 AddArgument
和 Execute
public void InvokeMyMethod(MyMethodDelegate method, params object[] args)
{
foreach(var arg in args)
{
method.AddArgument(arg);
}
method.Execute();
}
通过这种方式,我们所有的函数都可以保留其原始签名并接收多个参数而不是数组。
您的原始代码与此相去不远。只要使 InvokeMyMethod 仅采用抽象委托 class 并且在调用函数时显式指定委托类型(它不会推断类型),您就可以摆脱要求所有被调用方法具有相同签名的要求).我们可以利用 C# 中存在通用委托类型这一事实,因此我们不需要声明我们想要使用的所有可能的方法签名集。
如果您想调用具有 return 值的函数,您需要使用 Func<>
代替 Action<>
。
private void button1_Click(object sender, EventArgs e)
{
InvokeMyMethod((Action<string,int>) Test, "string", 1);
InvokeMyMethod((Action<string,int,Color>) TestN, "other string", 3, Color.Red);
}
public void InvokeMyMethod(Delegate method, params object[] args)
{
method.DynamicInvoke(args);
}
public void Test(string s, int i)
{
MessageBox.Show(string.Format("{0}{1}", s, i));
}
public void TestN(string s, int i, Color c)
{
// or, whatewer
MessageBox.Show(string.Format("{0}{1}{2}", s, i , c);
}
昨天我想创建一个 ExceptionHandler
class 例如我们可以传递给它:
- 异常
- 发生这种情况的方法
- 给该方法的参数
ExceptionHandler
将实现自定义业务逻辑并自动(或不)重新执行具有相同参数的方法。
The closest solution I found 是通过使用 delegate
这样的
private void button1_Click(object sender, EventArgs e)
{
InvokeMyMethod(Test, "string", 1);
InvokeMyMethod(TestN, "other string", 3, Color.Red);
}
public delegate void MyMethodDelegate(params object[] args);
public void InvokeMyMethod(MyMethodDelegate method, params object[] args)
{
method.DynamicInvoke(args);
}
public void Test(params object[] args)
{
if (args.Length < 2) return;
MessageBox.Show(string.Format("{0}{1}", args[0], args[1]));
}
public void TestN(params object[] args)
{
// or, whatewer
if (args.Length < 3) return;
MessageBox.Show(string.Format("{0}{1}{2}", args[0], args[1], args[2]));
}
然而,由于方法的签名,这个解决方案仍然不完美。我不希望我的所有方法都接收一个唯一参数 params object[] args
,而且这通常不可能直接实现,例如对于所有 UI 相关事件(Winform、ASP.NET、WPF 或其他)。
所以我想知道是否有一种方法可以将参数一个一个地传递给委托,然后仅在我们准备好时才执行该函数?
例如,这里是一个虚构的代码,其中包含不存在的方法 AddArgument
和 Execute
public void InvokeMyMethod(MyMethodDelegate method, params object[] args)
{
foreach(var arg in args)
{
method.AddArgument(arg);
}
method.Execute();
}
通过这种方式,我们所有的函数都可以保留其原始签名并接收多个参数而不是数组。
您的原始代码与此相去不远。只要使 InvokeMyMethod 仅采用抽象委托 class 并且在调用函数时显式指定委托类型(它不会推断类型),您就可以摆脱要求所有被调用方法具有相同签名的要求).我们可以利用 C# 中存在通用委托类型这一事实,因此我们不需要声明我们想要使用的所有可能的方法签名集。
如果您想调用具有 return 值的函数,您需要使用 Func<>
代替 Action<>
。
private void button1_Click(object sender, EventArgs e)
{
InvokeMyMethod((Action<string,int>) Test, "string", 1);
InvokeMyMethod((Action<string,int,Color>) TestN, "other string", 3, Color.Red);
}
public void InvokeMyMethod(Delegate method, params object[] args)
{
method.DynamicInvoke(args);
}
public void Test(string s, int i)
{
MessageBox.Show(string.Format("{0}{1}", s, i));
}
public void TestN(string s, int i, Color c)
{
// or, whatewer
MessageBox.Show(string.Format("{0}{1}{2}", s, i , c);
}