Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to create expression trees for C # value types, reference types, generics, collections

2025-04-12 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly introduces the relevant knowledge of how to create the expression tree of C# value type, reference type, generics, collection, the content is detailed and easy to understand, the operation is simple and fast, and has a certain reference value. I believe you will gain something after reading this article on how to create the expression tree of C# value types, reference types, generics, collections. Let's take a look.

First, define variables

In the C # expression tree, define a variable, using ParameterExpression.

There are two ways to create variable nodes

Expression.Parameter () Expression.Variable () / in addition, you can use Expression.Constant () to define a constant.

Both methods generate the ParameterExpression types Parameter () and Variable () both have two overloads. They create a ParameterExpression node that can be used to identify parameters or variables in the expression tree.

For using definitions:

Expression.Variable is used to declare local variables within a block.

Expression.Parameter is used to declare the parameters of the input value.

Let's look at the first one first.

Public static ParameterExpression Parameter (Type type) {return Parameter (type, name: null);} public static ParameterExpression Variable (Type type) {return Variable (type, name: null);}

From the perspective of the code, there is no difference.

And look at the overload with two parameters.

Public static ParameterExpression Parameter (Type type, string name) {Validate (type, allowByRef: true); bool byref = type.IsByRef; if (byref) {type = type.GetElementType ();} return ParameterExpression.Make (type, name, byref) } public static ParameterExpression Variable (Type type, string name) {Validate (type, allowByRef: false); return ParameterExpression.Make (type, name, isByRef: false);}

As you can see, there is only one allowByRef difference between the two. Paramter allows Ref and Variable does not.

The author did not find a specific difference between the official documentation and other author articles. After searching for stackoverflow and looking at the source code, I determined that the difference between them was that Variable could not use the ref type.

Literally, to declare a variable, you should use Expression.Variable, and the arguments passed in to the function should use Expression.Parameter.

Both value types and reference types are defined in this way.

Second, access the property fields and methods of variables / types

Access the properties of a variable or type, using the

Expression.Property ()

Access properties or fields of a variable / type, using the

Expression.PropertyOrField ()

A method to access a variable or type, using the

Expression.Call ()

Access property fields and methods

Expression.MakeMemberAccess

They all return a MemberExpression type.

In use, there is a small difference between instantiated / uninstantiated, which says variables or types.

It means that a value type that has been defined or an instantiated reference type is a variable

Type, which refers to a reference type, does not require instantiated static types or static property fields / methods.

The above explanation is not very rigorous, and the following example will explain it slowly.

1. Access Properti

Invoke the property using Expression.Property () or Expression.PropertyOrField ().

Call static type properties

Console is a static type, and Console.Title can get the actual location of the compiler program.

Console.WriteLine (Console.Title)

Use the expression tree to express as follows

MemberExpression member = Expression.Property (null, typeof (Console) .GetProperty ("Title"); Expression lambda = Expression.Lambda (member); string result = lambda.Compile () (); Console.WriteLine (result); Console.ReadKey ()

Because you are calling a statically typed property, the first parameter is empty.

The second parameter is a PropertyInfo type.

Call instance properties / fields

The C # code is as follows

List a = new List () {1,2,3}; int result = a.count; Console.WriteLine (result); Console.ReadKey ()

In the expression tree, call the properties of the instance

ParameterExpression a = Expression.Parameter (typeof (List), "a"); MemberExpression member = Expression.Property (a, "Count"); Expression lambda = Expression.Lambda (member, a); int result = lambda.Compile () (new List {1,2,3}); Console.WriteLine (result); Console.ReadKey ()

In addition to Expression.Property (), please test the other methods yourself, and I won't repeat them here.

two。 Call function

Use Expression.Call () to call a statically typed function or an instance of a function.

Call a statically typed function

Take Console as an example, call the WriteLine () method

Console.WriteLine ("call WriteLine method"); MethodCallExpression method = Expression.Call (null, typeof (Console) .GetMethod ("WriteLine", new Type [] {typeof (string)}), Expression.Constant ("call WriteLine method"); Expression lambda = Expression.Lambda (method); lambda.Compile () () Console.ReadKey ()

There are many overloading methods for Expression.Call (), and the commonly used overloading method is

Public static MethodCallExpression Call (Expression instance, MethodInfo method, params Expression [] arguments)

Because you are calling a statically typed function, the first instance is empty (instance means instance).

The second method is the overloaded method to call.

The last arguments is the parameter passed in.

Call the function of the instance

Write a class

Public class Test {public void Print (string info) {Console.WriteLine (info);}}

Call the Printf () method of the instance

Test test = new Test (); test.Print ("print out"); Console.ReadKey ()

The expression is as follows

ParameterExpression a = Expression.Variable (typeof (Test), "test"); MethodCallExpression method = Expression.Call (a, typeof (Test) .GetMethod ("Print", new Type [] {typeof (string)}), Expression.Constant ("print out")); Expression lambda = Expression.Lambda (method,a) Lambda.Compile () (new Test ()); Console.ReadKey ()

Note that Expression.Variable (typeof (Test), "test"); has only one variable defined and has not been initialized / assigned yet. For reference types, you need to instantiate.

The above method is passed in through external instantiation, which will be described later on how to instantiate within the expression.

Third, instantiate the reference type

Instantiate the reference type, use new, and then choose to call the appropriate constructor to set the value of the property.

So, according to the above steps, let's discuss it separately.

New

Use Expression.New () to call a type's constructor.

He has five overloads and two commonly used overloads:

Public static NewExpression New (ConstructorInfo constructor); public static NewExpression New (Type type)

Still use the above Test type

NewExpression newA = Expression.New (typeof (Test))

A constructor with no arguments by default, or only one constructor, called as above.

If you specify a constructor like this, you can

NewExpression newA = Expression.New (typeof (Test) .GetConstructor (xxxxxx))

I won't go into details here.

Assign a value to an attribute

You can assign a value to an attribute while instantiating a constructor.

Public static MemberInitExpression MemberInit (NewExpression newExpression, IEnumerable bindings); public static MemberInitExpression MemberInit (NewExpression newExpression, params MemberBinding [] bindings)

The two overloads are the same.

We change the Test class to

Public class Test {public int sample {get; set;} public void Print (string info) {Console.WriteLine (info);}}

And then

Var binding = Expression.Bind (typeof (Test) .GetMember ("sample") [0], Expression.Constant (10); create reference type Expression.MemberInit ()

Represents one or more members that call the constructor and initialize the new object.

If you instantiate a class, you can use the

NewExpression newA = Expression.New (typeof (Test)); MemberInitExpression test = Expression.MemberInit (newA, new List () {})

If you want to assign a value to a member when instantiating

NewExpression newA = Expression.New (typeof (Test)); / / assign a member of type Test var binding = Expression.Bind (typeof (Test) .GetMember ("sample") [0], Expression.Constant (10)); MemberInitExpression test = Expression.MemberInit (newA, new List () {binding}); example

Instantiate a type, call the constructor and assign a value to the member. The sample code is as follows

/ / call the constructor NewExpression newA = Expression.New (typeof (Test)); / / assign a member of type Test var binding = Expression.Bind (typeof (Test) .GetMember ("sample") [0], Expression.Constant (10)) / / instantiate a type MemberInitExpression test = Expression.MemberInit (newA, new List () {binding}) / / call method MethodCallExpression method1 = Expression.Call (test, typeof (Test) .GetMethod ("Print", new Type [] {typeof (string)}), Expression.Constant ("print")); / / call attribute MemberExpression method2 = Expression.Property (test, "sample") Expression lambda1 = Expression.Lambda (method1); lambda1.Compile () (); Expression lambda2 = Expression.Lambda (method2); int sample = lambda2.Compile () (); Console.WriteLine (sample); Console.ReadKey (); IV, instantiate the generic type in the call

Change the Test class to look like this

Public class Test {public void Print (T info) {Console.WriteLine (info);}}

The Test class is already a generic class, expression instantiation example

Static void Main (string [] args) {RunExpression (); Console.ReadKey ();} public static void RunExpression () {/ / call constructor NewExpression newA = Expression.New (typeof (Test)) / / instantiate a type MemberInitExpression test = Expression.MemberInit (newA, new List () {}) / / call method MethodCallExpression method = Expression.Call (test, typeof (Test) .GetMethod ("Print") .MakeGenericMethod (new Type [] {typeof (T)}), Expression.Constant ("print out"); Expression lambda1 = Expression.Lambda (method); lambda1.Compile () () Console.ReadKey ();} 5, define collection variables, initialize, and add elements

Collection types are represented by ListInitExpression.

To create a collection type, you need to use

ElementInit represents the initializer for a single element of the IEnumerable collection.

ListInit initializes a collection.

In C #, collections implement IEnumerable, and collections all have Add collect methods or properties.

To initialize a collection and add elements using C #, you can do this

List list = new List () {"a", "b"}; list.Add

In the expression tree, the element is initialized / added by calling the Add method through ElementInit.

Example

MethodInfo listAdd = typeof (List) .GetMethod ("Add"); / * * new List () * {* "a", * "b" *} * / ElementInit add1 = Expression.ElementInit (listAdd, Expression.Constant ("a"), Expression.Constant ("b"); / / Add ("666") ElementInit add2 = Expression.ElementInit (listAdd, Expression.Constant ("666"))

Example

MethodInfo listAdd = typeof (List) .GetMethod ("Add"); ElementInit add1 = Expression.ElementInit (listAdd, Expression.Constant ("a")); ElementInit add2 = Expression.ElementInit (listAdd, Expression.Constant ("b")); ElementInit add3 = Expression.ElementInit (listAdd, Expression.Constant ("666")); NewExpression list = Expression.New (typeof (List)) / / initialization value ListInitExpression setList = Expression.ListInit (list, add1, add2, add3); / / nothing to execute, just take a look at the output information Console.WriteLine (setList.ToString ()) MemberExpression member = Expression.Property (setList, "Count"); Expression lambda = Expression.Lambda (member); int result = lambda.Compile () (); Console.WriteLine (result); Console.ReadKey (); this is the end of the article on "how to create expression trees for C # value types, reference types, generics, collections". Thank you for reading! I believe you all have a certain understanding of "C # value types, reference types, generics, how to create the expression tree of a collection". If you want to learn more, you are welcome to follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report