gpt4 book ai didi

c# - Linq.Expression TryCatch - 将异常传递给 Catch block ?

转载 作者:行者123 更新时间:2023-12-04 15:30:38 25 4
gpt4 key购买 nike

所以我一直在修改 Linq.Expressions(如果有人可以建议一种更合适或更优雅的方式来做我正在做的事情,请随时加入)并且在尝试做某事时遇到了障碍。

假设我们有一个简单的数学课:

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接受一个 Expression 主体,然后是一个 CatchBlock 处理程序的集合。 returnMethodWithParametersAsObject是我们希望包装的表达式, Expression.Catch定义我们要捕获的异常是 InvalidCastException 类型,并且它的 Expression 主体是一个常量 55。

所以异常被处理了,但它没有多大用处,除非我想在抛出异常时总是返回一个静态值。所以回到 SimpleMath类我添加了一个新方法 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...Catch 块中,您实际上可以使用异常对象。例如。
try {
// Do stuff that causes an exception
} catch (InvalidCastException ex) {
// Do stuff with InvalidCastException ex
}

我可以在抛出异常时执行代码,但我似乎无法弄清楚如何像在普通的 Try...Catch 块中那样实际处理异常对象。

任何帮助,将不胜感激!

附言我知道您实际上不会按照我上面所做的方式组织任何事情,但我认为出于示例目的,有必要展示我想做的事情的机制。

最佳答案

您需要将捕获的异常传递给 CatchBlock表达式作为参数。
为此,您应该这样做:

  • 更改 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, object, object>>(tryCatchMethod2, parameters);
    Func<object, object, object> func2 = Expression.Lambda<Func<object, object, object>>(tryCatchMethod2, parameters).Compile();
    object result2 = func2(20, "f"); // result = 100
  • 关于c# - Linq.Expression TryCatch - 将异常传递给 Catch block ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45982983/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com