所以我一直在修补Linq.Expressions(如果有人可以建议一个更合适或更优雅的方式来做我所做的事情,请随时参加),并试图做一些事情已经碰壁了。Linq.Expression TryCatch - 将异常传递给Catch Block?
让我们想象一下,我们有一个简单的数学类:
public class SimpleMath {
public int AddNumbers(int number1, int number2) {
return number1 + number2;
}
}
我决定我想我们AddNumbers
方法转换成一个简单的Func<object, object, object>
委托。
要做到这一点,我做了以下内容:
// Two collections, one for Type Object paramaters and one for converting to Type int.
List<ParameterExpression> parameters = new List<ParameterExpression>();
List<Expression> convertedParameters = new List<Expression>();
// Populate collections with Parameter and conversion
ParameterExpression parameter1 = Expression.Parameter(typeof(object));
parameters.Add(parameter1);
convertedParameters.Add(Expression.Convert(parameter1, typeof(int)));
ParameterExpression parameter2 = Expression.Parameter(typeof(object));
parameters.Add(parameter2);
convertedParameters.Add(Expression.Convert(parameter2, typeof(int)));
// Create instance of SimpleMath
SimpleMath simpleMath = new SimpleMath();
// Get the MethodInfo for the AddNumbers method
MethodInfo addNumebrsMethodInfo = simpleMath.GetType().GetMethods().Where(x => x.Name == "AddNumbers").ToArray()[0];
// Create MethodCallExpression using the SimpleMath object, the MethodInfo of the method we want and the converted parameters
MethodCallExpression returnMethodWithParameters = Expression.Call(Expression.Constant(simpleMath), addNumebrsMethodInfo, convertedParameters);
// Convert the MethodCallExpression to return an Object rather than int
UnaryExpression returnMethodWithParametersAsObject = Expression.Convert(returnMethodWithParameters, typeof(object));
// Create the Func<object, object, object> with our converted Expression and Parameters of Type Object
Func<object, object, object> func = Expression.Lambda<Func<object, object, object>>(returnMethodWithParametersAsObject, parameters).Compile();
object result = func(20, 40); // result = 60
所以,如果你运行该代码func
应该返回简单的计算。然而,它接受类型对象,这显然离开它打开在运行时的问题,例如参数:
object result1 = func(20, "f"); // Throws InvalidCastException
所以我想换的方法,在Try...Catch
(显然这个确切的问题将在编译有所回升如果我们正在处理直接调用AddNumbers
并传递一个字符串作为参数)。
以抓住这个例外,我可以做到以下几点:
TryExpression tryCatchMethod = TryExpression.TryCatch(returnMethodWithParametersAsObject, Expression.Catch(typeof(InvalidCastException), Expression.Constant(55, typeof(object))));
Func<object, object, object> func = Expression.Lambda<Func<object, object, object>>(tryCatchMethod, parameters).Compile();
object result = func(20, "f"); // result = 55
的TryExpression.TryCatch
需要一个表达的身体,然后CatchBlock处理程序的集合。 returnMethodWithParametersAsObject
是我们希望包裹的表达,Expression.Catch
定义了我们想捕获异常是InvalidCastException类型和它表达的身体是一个常数,55
所以异常的处理,但除非我想这是没有多大用处在抛出异常时总是返回一个静态值。于是久违的SimpleMath
I类添加一个新方法HandleException
:
public class SimpleMath {
public int AddNumbers(int number1, int number2) {
return number1 + number2;
}
public int HandleException() {
return 100;
}
}
而且同样的过程上面我转换的新方法的表达式:
MethodInfo handleExceptionMethodInfo = simpleMath.GetType().GetMethods().Where(x => x.Name == "HandleException").ToArray()[0];
MethodCallExpression returnMethodWithParameters2 = Expression.Call(Expression.Constant(simpleMath), handleExceptionMethodInfo);
UnaryExpression returnMethodWithParametersAsObject2 = Expression.Convert(returnMethodWithParameters2, typeof(object));
然后创建TryCatch块时使用它:
TryExpression tryCatchMethod2 = TryExpression.TryCatch(returnMethodWithParametersAsObject, Expression.Catch(typeof(InvalidCastException), returnMethodWithParametersAsObject2));
Func<object, object, object> func = Expression.Lambda<Func<object, object, object>>(tryCatchMethod2, parameters).Compile();
object result = func(20, "f"); // result = 100
所以当InvalidCastException
抛出的SimpleMath.HandleException
方法这段时间将被执行。到目前为止,如果出现异常,我现在可以执行一些代码。
我现在的问题是,在一个正常的行内尝试...赶上块你实际上有你的处置异常对象。例如。
try {
// Do stuff that causes an exception
} catch (InvalidCastException ex) {
// Do stuff with InvalidCastException ex
}
时抛出一个异常,我可以执行代码,但我似乎无法弄清楚如何真正得到我的手异常对象上,就像您在普通try ... catch块。
任何帮助,将不胜感激!
p.s.我知道你不会以上述方式组织任何事情,但我认为有必要举例说明我想要做什么的机制。
问题比较对我的知识,而是一个建议,可以帮助有关传递异常太复杂:抓{抛出;}。这会将你的异常传递给调用方法(你必须处理它或程序将停止!)。如果你想把你的手放在一个已经存在的函数的例外,把它作为一个动作/ func在你自己的TryCatch方法中,如果发生了什么错误,返回一个异常,如果一切正常,你认为是好的(空?) – Kinxil