public static Catch ( System.Linq.Expressions.ParameterExpression variable, |
||
variable | System.Linq.Expressions.ParameterExpression | A |
body | The body of the catch statement. | |
Résultat |
public EvaluationCallback Create(Node node) { var compilerstate = new CompilerState { FunctionState = Exp.Parameter(typeof(Character), "state"), ErrorVariable = Exp.Parameter(typeof(bool), "error") }; var result = Make(compilerstate, node); if (result.Type == typeof(bool)) { result = ToInteger(result); } if (result.Type == typeof(int) || result.Type == typeof(float)) { // int or float convert to number var constructor = typeof(Number).GetConstructor(new[] { result.Type }); result = Exp.New(constructor, new[] { result }); // wrap the evaluation in a try..catch var exceptionParameter = Exp.Parameter(typeof(Exception), "e"); var writeLineMethod = typeof(Console).GetMethod(nameof(Console.WriteLine), new Type[] { typeof(string) }); var toStringMethod = typeof(Exception).GetMethod(nameof(Exception.ToString)); var catchBody = Exp.Block( Exp.Call(null, writeLineMethod, Exp.Call(exceptionParameter, toStringMethod)), Exp.Constant(new Number(0))); result = Exp.TryCatch(result, Exp.Catch(exceptionParameter, catchBody)); // create lambda var func = Exp.Lambda <Func <Character, bool, Number> >(result, compilerstate.FunctionState, compilerstate.ErrorVariable).Compile(); return(new EvaluationCallback(o => func(o, false))); } throw new Exception(); }
public void TryCatchTypeBody() { var expected = LinqExpression.TryCatch( LinqExpression.Constant(0L), LinqExpression.Catch( typeof(Exception), LinqExpression.Constant(0L))); using var g = new GraphEngine.Graph(); g.LoadFromString(@" @prefix : <http://example.com/> . :s :tryBody _:zero ; :tryHandlers ( [ :catchType [ :typeName ""System.Exception"" ; ] ; :catchBody _:zero ; ] ) ; . _:zero :constantValue 0 ; . "); var s = g.GetUriNode(":s"); var actual = Expression.Parse(s).LinqExpression; Console.WriteLine(actual.GetDebugView()); actual.Should().Be(expected); }
public LambdaExpression CreateLambda(Type from, Type to) { var input = Ex.Parameter(from, "input"); var convert = ConvertMethod(from, to); var exception = Ex.Parameter(typeof(Exception), "exception"); var block = Ex.TryCatch( Result(to, Ex.Call(convert, convert.GetParameters().Select(pi => getParameter(pi, input)))), Ex.Catch(exception, NoResult(to))); var lambda = Ex.Lambda(block, input); return(lambda); }
public void TryCatchVariableBodyFilter() { var expected = LinqExpression.TryCatch( LinqExpression.Constant(0L), LinqExpression.Catch( LinqExpression.Parameter( typeof(Exception)), LinqExpression.Constant(0L), LinqExpression.Equal( LinqExpression.Constant(0L), LinqExpression.Constant(0L)))); using var g = new GraphEngine.Graph(); g.LoadFromString(@" @prefix : <http://example.com/> . @prefix xt: <http://example.com/ExpressionTypes/> . :s :tryBody _:zero ; :tryHandlers ( [ :catchVariable [ :parameterType [ :typeName ""System.Exception"" ; ] ; ] ; :catchBody _:zero ; :catchFilter [ :binaryExpressionType xt:Equal ; :binaryLeft _:zero ; :binaryRight _:zero ; ] ; ] ) ; . _:zero :constantValue 0 ; . "); var s = g.GetUriNode(":s"); var actual = Expression.Parse(s).LinqExpression; Console.WriteLine(actual.GetDebugView()); actual.Should().Be(expected); }
public static Expression <Func <string[], int> > WrapMain(Expression program) { LabelTarget label = Expression.Label(typeof(int)); BlockExpression programReturningNoErrorCode = Expression.Block(program, Expression.Constant(0)); Expression <Action <Exception> > writeLine = s => Console.Error.WriteLine(s); ParameterExpression exitException = Expression.Variable(typeof(ExitException)); ParameterExpression exception = Expression.Variable(typeof(Exception)); TryExpression programCatchingExceptions = Expression.TryCatch(programReturningNoErrorCode, Expression.Catch(exitException, Expression.Property(exitException, "Code")), Expression.Catch(exception, Expression.Block(writeLine.eInvoke(exception), Expression.Constant(1)))); LabelExpression returnLabel = Expression.Label(label, programCatchingExceptions); ParameterExpression parameter = Expression.Parameter(typeof(string[]), "args"); Expression <Func <string[], int> > lambda = Expression.Lambda <Func <string[], int> >(returnLabel, parameter); return(lambda); }
static void Main() { var asm = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("bar"), AssemblyBuilderAccess.Save); var mod = asm.DefineDynamicModule("bar.dll"); var typ = mod.DefineType("Foo"); var lblRet = Expression.Label(typeof(int)); var lbl1 = Expression.Label(typeof(int)); var ex = Expression.Parameter(typeof(Exception)); var expressions = new Expression[] { Expression.TryFault( Expression.Constant(1), Expression.Constant(2) ), Expression.Block( Expression.TryFault( Expression.Goto(lblRet, Expression.Constant(1)), Expression.Constant(2) ), Expression.Label(lblRet, Expression.Constant(0)) ), Expression.Block( Expression.TryFault( Expression.Block( Expression.Goto(lblRet, Expression.Constant(1)), Expression.Constant(2) ), Expression.Constant(3) ), Expression.Label(lblRet, Expression.Constant(0)) ), Expression.Block( Expression.TryFault( Expression.Block( Expression.Goto(lbl1, Expression.Constant(1)), Expression.Goto(lblRet, Expression.Constant(2)) ), Expression.Constant(3) ), Expression.Label(lbl1, Expression.Constant(-1)), Expression.Label(lblRet, Expression.Constant(0)) ), Expression.TryCatch( Expression.Constant(1), Expression.Catch(ex, Expression.Constant(2), Expression.Constant(true)) ), }; var i = 0; foreach (var expression in expressions) { var mtd = typ.DefineMethod("M" + i, MethodAttributes.Public | MethodAttributes.Static, typeof(int), new Type[0]); Expression.Lambda <Func <int> >(expression).CompileToMethod(mtd); var cw = Expression.Lambda <Func <int> >(expression).CompileWithExceptionHandling(); cw(); i++; } }
public void MiscellaneousExpression_Try() { var tryCatch = Expr.TryCatch(Expr.Constant(false), Expr.Catch(typeof(Exception), Expr.Constant(false))); UnsupportedExpr(Property.Id, id => tryCatch, ExpressionType.Try); }
static LambdaExpression ApplyMethodHandler(string functionName, LambdaExpression functionLambda, IFunctionExecutionHandler handler) { // public static int MyMethod(object arg0, int arg1) { ... } // becomes: // (the 'handler' object is captured and called mh) // public static int MyMethodWrapped(object arg0, int arg1) // { // var fhArgs = new FunctionExecutionArgs("MyMethod", new object[] { arg0, arg1}); // int result = default(int); // try // { // fh.OnEntry(fhArgs); // if (fhArgs.FlowBehavior == FlowBehavior.Return) // { // result = (int)fhArgs.ReturnValue; // } // else // { // // Inner call // result = MyMethod(arg0, arg1); // fhArgs.ReturnValue = result; // fh.OnSuccess(fhArgs); // result = (int)fhArgs.ReturnValue; // } // } // catch ( Exception ex ) // { // fhArgs.Exception = ex; // fh.OnException(fhArgs); // // Makes no sense to me yet - I've removed this FlowBehavior enum value. // // if (fhArgs.FlowBehavior == FlowBehavior.Continue) // // { // // // Finally will run, but can't change return value // // // Should we assign result...? // // // So Default value will be returned....????? // // fhArgs.Exception = null; // // } // // else // if (fhArgs.FlowBehavior == FlowBehavior.Return) // { // // Clear the Exception and return the ReturnValue instead // // Finally will run, but can't further change return value // fhArgs.Exception = null; // result = (int)fhArgs.ReturnValue; // } // else if (fhArgs.FlowBehavior == FlowBehavior.ThrowException) // { // throw fhArgs.Exception; // } // else // if (fhArgs.FlowBehavior == FlowBehavior.Default || fhArgs.FlowBehavior == FlowBehavior.RethrowException) // { // throw; // } // } // finally // { // fh.OnExit(fhArgs); // // NOTE: fhArgs.ReturnValue is not used again here...! // } // // return result; // } // } // CONSIDER: There are some helpers in .NET to capture the exception context, which would allow us to preserve the stack trace in a fresh throw. // Ensure the handler object is captured. var mh = Expression.Constant(handler); var funcName = Expression.Constant(functionName); // Prepare the functionHandlerArgs that will be threaded through the handler, // and a bunch of expressions that access various properties on it. var fhArgs = Expr.Variable(typeof(FunctionExecutionArgs), "fhArgs"); var fhArgsReturnValue = SymbolExtensions.GetProperty(fhArgs, (FunctionExecutionArgs mea) => mea.ReturnValue); var fhArgsException = SymbolExtensions.GetProperty(fhArgs, (FunctionExecutionArgs mea) => mea.Exception); var fhArgsFlowBehaviour = SymbolExtensions.GetProperty(fhArgs, (FunctionExecutionArgs mea) => mea.FlowBehavior); // Set up expressions to call the various handler methods. // TODO: Later we can determine which of these are actually implemented, and only write out the code needed in the particular case. var onEntry = Expr.Call(mh, SymbolExtensions.GetMethodInfo <IFunctionExecutionHandler>(meh => meh.OnEntry(null)), fhArgs); var onSuccess = Expr.Call(mh, SymbolExtensions.GetMethodInfo <IFunctionExecutionHandler>(meh => meh.OnSuccess(null)), fhArgs); var onException = Expr.Call(mh, SymbolExtensions.GetMethodInfo <IFunctionExecutionHandler>(meh => meh.OnException(null)), fhArgs); var onExit = Expr.Call(mh, SymbolExtensions.GetMethodInfo <IFunctionExecutionHandler>(meh => meh.OnExit(null)), fhArgs); // Create the new parameters for the wrapper var outerParams = functionLambda.Parameters.Select(p => Expr.Parameter(p.Type, p.Name)).ToArray(); // Create the array of parameter values that will be put into the method handler args. var paramsArray = Expr.NewArrayInit(typeof(object), outerParams.Select(p => Expr.Convert(p, typeof(object)))); // Prepare the result and ex(ception) local variables var result = Expr.Variable(functionLambda.ReturnType, "result"); var ex = Expression.Parameter(typeof(Exception), "ex"); // A bunch of helper expressions: // : new FunctionExecutionArgs(new object[] { arg0, arg1 }) var fhArgsConstr = typeof(FunctionExecutionArgs).GetConstructor(new[] { typeof(string), typeof(object[]) }); var newfhArgs = Expr.New(fhArgsConstr, funcName, paramsArray); // : result = (int)fhArgs.ReturnValue var resultFromReturnValue = Expr.Assign(result, Expr.Convert(fhArgsReturnValue, functionLambda.ReturnType)); // : fhArgs.ReturnValue = (object)result var returnValueFromResult = Expr.Assign(fhArgsReturnValue, Expr.Convert(result, typeof(object))); // : result = function(arg0, arg1) var resultFromInnerCall = Expr.Assign(result, Expr.Invoke(functionLambda, outerParams)); // Build the Lambda wrapper, with the original parameters var lambda = Expr.Lambda( Expr.Block(new[] { fhArgs, result }, Expr.Assign(fhArgs, newfhArgs), Expr.Assign(result, Expr.Default(result.Type)), Expr.TryCatchFinally( Expr.Block( onEntry, Expr.IfThenElse( Expr.Equal(fhArgsFlowBehaviour, Expr.Constant(FlowBehavior.Return)), resultFromReturnValue, Expr.Block( resultFromInnerCall, returnValueFromResult, onSuccess, resultFromReturnValue))), onExit, // finally Expr.Catch(ex, Expr.Block( Expr.Assign(fhArgsException, ex), onException, Expr.IfThenElse( Expr.Equal(fhArgsFlowBehaviour, Expr.Constant(FlowBehavior.Return)), Expr.Block( Expr.Assign(fhArgsException, Expr.Constant(null, typeof(Exception))), resultFromReturnValue), Expr.IfThenElse( Expr.Equal(fhArgsFlowBehaviour, Expr.Constant(FlowBehavior.ThrowException)), Expr.Throw(fhArgsException), Expr.Rethrow())))) ), result), functionName, outerParams); return(lambda); }
internal System.Linq.Expressions.CatchBlock ToCatchBlock() => SysExpr.Catch(Variable.ToParameterExpression(), Body.ToExpression());
public static Expression TryNoCatch(this Expression expression) => Expression.TryCatch(expression, Expression.Catch(typeof(Exception).ToParameter(), Expression.Empty()));