I had a class with some common error handling code, and I wanted to pass in the method and arguments to call, but I couldn't quite come up with the syntax. What I want to do is roughly this:
我有一个带有一些常见错误处理代码的类,我想传入方法和参数来调用,但我无法提出语法。我想要做的就是这个:
private void InvokeHelper(Delegate method, params object[] args)
{
bool retry = false;
do
{
try
{
method.DynamicInvoke(args);
retry = false;
}
catch (MyException ex)
{
retry = HandleException(ex);
}
} while (retry);
}
and then be able to do things like:
然后能够做以下事情:
InvokeHelper(foo.MethodA, a, b, c);
InvokeHelper(foo.MethodB, x, y );
This gets a compiler error converting foo.MethodA and foo.MethodB into System.Delegate. I came up with the workaround below (and I actually like it better because then I get type checking on my arguments to my methods), but I'm curious if there's a way to do what I was originally trying to do? I know I could use foo.GetType().GetMethod("MethodA")
and invoke that, but I was trying to avoid reflection. I mainly just want to understand how methods are dynamically invoked in .net.
这会将编译器错误转换为将foo.MethodA和foo.MethodB转换为System.Delegate。我提出了下面的解决方法(我实际上更喜欢它,因为我得到了我的方法的参数的类型检查),但我很好奇是否有办法做我原本想做的事情?我知道我可以使用foo.GetType()。GetMethod(“MethodA”)并调用它,但我试图避免反射。我主要想了解如何在.net中动态调用方法。
Workaround:
private delegate void EmptyDelegate();
private void InvokeHelper(EmptyDelegate method)
{
bool retry = false;
do
{
try
{
method.Invoke();
retry = false;
}
catch (MyException ex)
{
retry = HandleException(ex);
}
} while (retry);
}
then call:
InvokeHelper(delegate() { foo.MethodA(a, b, c); });
InvokeHelper(delegate() { foo.MethodB(x, y); });
2 个解决方案
#1
4
First off, your signature is
首先,你的签名是
private void InvokeHelper(Delegate method, params object[] args)
Yet you're making the mistake that you have to group your args into an array to call this method:
然而,你犯了一个错误,你必须将你的args分组成一个数组来调用这个方法:
InvokeHelper(foo.MethodA, new object[] { a, b, c});
The parms
keyword tells the compiler to do this for you; you can call this method thusly:
parms关键字告诉编译器为您执行此操作;你可以这样调用这个方法:
InvokeHelper(foo.MethodA, a, b, c);
Second, if you're targeting 3.0 or greater, don't use Delegate, use Action:
其次,如果您的目标是3.0或更高版本,请不要使用Delegate,请使用Action:
private void InvokeHelper(Action method)
and call it this way:
并这样称呼它:
InvokeHelper(()=> MyMethodToInvoke(a, b, c));
which is just an overall better way of doing this.
这只是一个更好的方式来做到这一点。
As to why you're getting the compiler issue, its because System.Delegates hate us. Its a simple fact. That, and because there is no implicit cast from method group to Delegate.
至于为什么你会遇到编译器问题,因为System.Delegates讨厌我们。这是一个简单的事实。那,并且因为没有从方法组到Delegate的隐式转换。
#2
2
Here's a re-write, following Will's advice to use Action:
按照Will的建议使用Action,这是一个重写:
private void InvokeHelper(Action method)
{
bool retry = false;
do
{
try
{
method();
retry = false;
}
catch (MyException ex)
{
retry = HandleException(ex);
}
} while (retry);
}
public void Test()
{
FooClass foo = new FooClass();
InvokeHelper( () => foo.MethodA(1, "b", 3) );
InvokeHelper( () => foo.MethodB(2, "y"));
}
#1
4
First off, your signature is
首先,你的签名是
private void InvokeHelper(Delegate method, params object[] args)
Yet you're making the mistake that you have to group your args into an array to call this method:
然而,你犯了一个错误,你必须将你的args分组成一个数组来调用这个方法:
InvokeHelper(foo.MethodA, new object[] { a, b, c});
The parms
keyword tells the compiler to do this for you; you can call this method thusly:
parms关键字告诉编译器为您执行此操作;你可以这样调用这个方法:
InvokeHelper(foo.MethodA, a, b, c);
Second, if you're targeting 3.0 or greater, don't use Delegate, use Action:
其次,如果您的目标是3.0或更高版本,请不要使用Delegate,请使用Action:
private void InvokeHelper(Action method)
and call it this way:
并这样称呼它:
InvokeHelper(()=> MyMethodToInvoke(a, b, c));
which is just an overall better way of doing this.
这只是一个更好的方式来做到这一点。
As to why you're getting the compiler issue, its because System.Delegates hate us. Its a simple fact. That, and because there is no implicit cast from method group to Delegate.
至于为什么你会遇到编译器问题,因为System.Delegates讨厌我们。这是一个简单的事实。那,并且因为没有从方法组到Delegate的隐式转换。
#2
2
Here's a re-write, following Will's advice to use Action:
按照Will的建议使用Action,这是一个重写:
private void InvokeHelper(Action method)
{
bool retry = false;
do
{
try
{
method();
retry = false;
}
catch (MyException ex)
{
retry = HandleException(ex);
}
} while (retry);
}
public void Test()
{
FooClass foo = new FooClass();
InvokeHelper( () => foo.MethodA(1, "b", 3) );
InvokeHelper( () => foo.MethodB(2, "y"));
}