C # 3.0 features 10 new expression tree 04 executing the expression

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.

Lambda expressions to function

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  CompileToMethodmembers. 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.

Execution and survival

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 .

Precautions

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.

to sum up

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.

 

Guess you like

Origin www.cnblogs.com/SavionZhang/p/11183414.html