让我们假设我们有一个简单的数学课:
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> with our converted Expression and Parameters of Type Object Func<object,object> func = Expression.Lambda<Func<object,object>>(returnMethodWithParametersAsObject,parameters).Compile(); object result = func(20,40); // result = 60
因此,如果您运行该代码,则func应返回简单计算.但是,它接受Type对象的参数,这显然会使它在运行时遇到问题,例如:
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>>(tryCatchMethod,parameters).Compile(); object result = func(20,"f"); // result = 55
TryExpression.TryCatch接受一个Expression主体,然后是一个CatchBlock处理程序的集合. returnMethodWithParametersAsObject是我们希望包装的表达式,Expression.Catch定义我们要捕获的Exception是Type InvalidCastException,它的Expression主体是常量,55.
因此处理异常,但除非我想在抛出异常时始终返回静态值,否则它没有多大用处.所以返回SimpleMath类我添加了一个新方法HandleException:
public class SimpleMath { public int AddNumbers(int number1,int number2) { return number1 + number2; } public int HandleException() { return 100; } }
按照上面的相同过程,我将新方法转换为Expression:
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,returnMethodWithParametersAsObject2)); Func<object,object>>(tryCatchMethod2,"f"); // result = 100
所以这次抛出InvalidCastException时,将执行SimpleMath.HandleException方法.到目前为止一切顺利,我现在可以在出现异常时执行一些代码.
我现在的问题是,在一个正常的内联Try … Catch块中你实际上有你可以使用的异常对象.例如.
try { // Do stuff that causes an exception } catch (InvalidCastException ex) { // Do stuff with InvalidCastException ex }
我可以在抛出异常时执行代码,但我似乎无法弄清楚如何实际上如同在正常的Try … Catch块中那样触及异常对象.
任何帮助,将不胜感激!
附:我知道你实际上并没有按照我上面的方式组织任何事情,但我认为有必要举例说明我想做什么的机制.
解决方法
为此你应该这样做:
>更改HandleException的签名.它将以异常作为参数:
public int HandleException(InvalidCastException exp) { // Put here some real logic. I tested it using line below Console.WriteLine(exp.Message); return 100; }
>使用CatchBlock.Variable将处理的异常传递给catch块.您可以设置它使用构造函数.阅读以下代码中的评论:
// Create parameter that will be passed to catch block var excepParam = Expression.Parameter(typeof(InvalidCastException)); MethodInfo handleExceptionMethodInfo = simpleMath.GetType().getmethods().Where(x => x.Name == "HandleException").ToArray()[0]; MethodCallExpression returnMethodWithParameters2 = Expression.Call(Expression.Constant(simpleMath),handleExceptionMethodInfo,excepParam); UnaryExpression returnMethodWithParametersAsObject2 = Expression.Convert(returnMethodWithParameters2,typeof(object)); // Put created parameter before to CatchBlock.Variable using Expression.Catch // that takes the first argument as ParameterExpression TryExpression tryCatchMethod2 = TryExpression.TryCatch(returnMethodWithParametersAsObject,Expression.Catch(excepParam,returnMethodWithParametersAsObject2)); var exppp = Expression.Lambda<Func<object,parameters); Func<object,object> func2 = Expression.Lambda<Func<object,parameters).Compile(); object result2 = func2(20,"f"); // result = 100
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。