Expression tree is a data structure of some code. It is not compiled and executable code. If you want to execute .NET code represented by an expression tree, it must be converted to IL executable instructions.
Or may be derived from any LambdaExpression LambdaExpression convert any type of executable IL. Other types of expression can not be converted directly into code. This restriction has little effect in practice. Lambda expressions are the only type of expression you can pass into executable intermediate language (IL) performed. (Direct execution think ConstantExpression
what it means. Does that mean anything useful?) LambdaExpression
Or derived from LambdaExpression
any expression of the type of tree can be converted into IL. Expression type Expression<TDelegate>
is the only specific example of .NET Core library. It is used to represent mapped to any delegate type of expression. Since this type is mapped to a delegate type, so .NET expressions can be checked, and the production of IL lambda expressions to match the appropriate delegate signature.
In most cases, this will create a simple mapping between expressions and their corresponding delegate. For example, the Expression<Func<int>>
expression tree representation is converted to a Func<int>
type of commission. For any return type and parameter lists Lambda expressions, there is a delegate type: This type is a type of executable code of the target indicated by the Lambda expressions.
LambdaExpression
Type for converting the expression tree comprising executable code Compile
and CompileToMethod
members. Compile
Way to create a delegate. CompileToMethod
Methods for IL updates compiled output expression tree MethodBuilder
object. Please note, CompileToMethod
only available in full desktop framework, not for .NET Core.
Also can be selectively provided DebugInfoGenerator
, symbolic debug information it receives delegate object generated. This allows you to convert the expression tree to a delegate object, and has a complete debug information generated by the delegate.
Use the following code an expression converted to a delegate:
Expression The <Func < int >> = the Add () => . 1 + 2 ; var FUNC = add.Compile (); // production commissioned var answer = FUNC (); // execution request Console.WriteLine (answer);
Please note that the delegate type based on the type of expression. If you want to use a strongly typed fashion delegate object, you must know the return type and parameter list. LambdaExpression.Compile()
Method return Delegate
types. Must convert it to the proper delegate type, so that the tool checks the parameter list or return any compile-time type.
By calling the call LambdaExpression.Compile()
to execute code when the delegate is created. It can be viewed above, which add.Compile()
returns a delegate. By calling func()
call the delegate will execute the code.
The delegate represents the code expression tree. The delegate can keep a handle and call it later. You do not need to compile the expression tree each time you want to execute code expression tree represents. (Remember, the expression tree is immutable, and after compiling the same expression trees will create a delegate execute the same code .)
To remind you not to avoid unnecessary compilation by calling any attempt to create a more sophisticated caching mechanism used to improve performance. Compare two arbitrary expression tree to determine if they represent the same algorithm, whether it will take a long time to execute. You may find that by avoiding LambdaExpression.Compile()
any additional calls computation time savings will more than execute code (code determines which can lead to two different expression tree the same executable code) it takes time .
Compile the lambda expression to a delegate and call the delegate is one of the most simple operation that can be performed to expression trees. But even perform this simple operation, there are several things you must pay attention to.
Lambda expressions will create a closure of any local variables referenced in the expression. Must ensure that any variable as part of a delegation of the call Compile
available at the position and the results of the commission.
Under normal circumstances, the compiler will ensure this. However, if the expression access implementation IDisposable
variables, the code may release the object when the expression tree still retains the object.
For example, this code works fine, because int
not achieved IDisposable
:
Private static Func < int , int > CreateBoundFunc () { var Constant = . 5 ; // constant expression tree captured by the Expression <Func < int , int >> = expression The (B) => Constant + B; var rval = expression The. the Compile (); return rval; }
It has been commissioned to capture the local variable constant
references. In the later execution CreateBoundFunc
after the function returns, you can always access the variable.
However, consider implementing IDisposable
this class (designed by man):
public class Resource : IDisposable { private bool isDisposed = false; public int Argument { get { if (!isDisposed) return 5; else throw new ObjectDisposedException("Resource"); } } public void Dispose() { isDisposed = true; } }
If it is used in an expression shown below is performed Resource.Argument
when the code attribute references appears ObjectDisposedException
:
Private static Func < int , int > CreateBoundResource () { the using ( var Constant = new new the Resource ()) // constant expression tree captured by { the Expression <Func < int , int >> = expression The (B) => constant.Argument + B; var rval = expression.Compile (); return rval; } }
Returned from this method has been commissioned for the release of the constant
closure object. (It has been released because it has been using
declared in the statement.)
Now, when executing the delegate returned from this method, it will lead in the implementation ObjectDisposedException
.
It appears to indicate that the compile-time run-time error structure is indeed very strange, but this is a normal phenomenon when using the expression tree.
This is a problem a lot of arrangement, it is difficult to provide general guidance for avoiding this problem. When defining expression, careful local variables, and when you create a public API returns an expression tree may be prudent to access the current object (a this
representation) state.
Expression code may refer to other assembly methods or properties. The expression is defined, compilation or when you call the result of the commission, the assembly must be accessible. In the case where it does not exist, we will encounter ReferencedAssemblyNotFoundException
.
It can be compiled expression tree that represents the lambda expression to create an executable delegate. This provides a mechanism, represented by the code expression tree for execution.
Expression tree that it would create any given configuration code execution. As long as the environment matching compile and execute the code to create the environment of the expression, then everything will be expected. If you are not working as expected, then the error is very easy to predict, and will catch these errors in the first test any code using an expression tree.