this code outputs "out value".
class P
{
public static void Main()
{
string arg = null;
try
{
Method(out arg);
}
catch
{
}
Console.WriteLine(arg);
}
public static void Method(out string arg)
{
arg = "out value";
throw new Exception();
}
}
but this one doesn't.
class P
{
public static void Main()
{
object[] args = new object[1];
Me开发者_运维问答thodInfo mi = typeof(P).GetMethod("Method");
try
{
mi.Invoke(null, args);
}
catch
{
}
Console.WriteLine(args[0]);
}
public static void Method(out string arg)
{
arg = "out value";
throw new Exception();
}
}
how can I get both "out value" and an exception when using reflection?
The exception bypassed the code in MethodInfo.Invoke() that copies the [out] value from the stack frame back into the object array. The value on the stack frame that Invoke() created behaves just like it does in your 1st snippet. But that's where the similarities end.
The only way is to overload your method in a manner that accounts for the possibility of an exception and then pass one in "just in case". The following produces what I think you're looking for. The problem as I understand it is that reflection does not perform direct manipulation of the addresses passed in by reference. The addresses are not affected until the method end point is reached without exception. Possibly a memory protection or memory security scheme from MS.
class P
{
public static void Main()
{
object[] args = { "1", new Exception()};
MethodInfo mi = typeof(P).GetMethod("Method");
try
{
mi.Invoke(null, args);
}
catch
{
}
Console.WriteLine(args[0].ToString());
Console.WriteLine(args[1].ToString());
}
public static void Method(ref string arg, ref Exception ex)
{
try
{
arg = "out value";
throw new Exception();
}
catch (Exception exc)
{
ex = exc;
}
}
}
I would propose to change the method to return Result object instead of out parameter. Result object can contain exception and also the value of your arg.
If the issue is, how do you catch that an exception has occured and you're working with a Windows Forms application, have you tried looking at the Thread Exception Event and combining it with the SetUnhandledExceptionMode()?
Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
HandleException(e.Exception);
}
The out parameter is undefined if the method throws an exception. You can see this by not initialising it to null in the first example, then the code won't compile.
So, it makes sense for the Invoke method not to return the undefined value if the method throws an exception.
精彩评论