練習は、式ツリーを行使する:C#の値型、参照型、ジェネリック、コレクションは、関数を呼び出します

練習は、式ツリーを行使する:C#の値型、参照型、ジェネリック、コレクションは、関数を呼び出します

IMG

まず、変数の定義

C#の式ツリー、変数の定義、使用ParameterExpression

この方法は、変数ノードを作成し、両者は、あります

Expression.Parameter()
Expression.Variable()
// 另外,定义一个常量可以使用 Expression.Constant()。

どちらの方法でも生成されているParameterExpressionタイプParameter()Variable()の二つはオーバーロードしています。これらは、式ツリー内のパラメータまたは変数を識別するために使用することができるParameterExpressionノードを作成します。

定義について:

Expression.Variable ブロック内のローカル変数を宣言するために使用します。

Expression.Parameter文の入力パラメータ値。

初見

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

ビューのコードポイントからは、違いはありません。

二つのパラメータで過負荷を見てください

        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);
        }

あなたが見ることができるように、唯一のallowByRef両方が違いを登場、PARAMTERは参考許され、変数が許可されていません。

公式文書や他の著者で、著者は、特定の違いを発見していないそれらの間の差異を決定するために、ソースコードを検索し、表示するstackoverflowのは、あなたが参照変数の型を使用できないことです後、何です。

文字通りの意味からは、変数を使用する必要があります宣言するExpression.Variable渡す関数パラメータを使用する必要があります、Expression.Parameter

値型または参照型かどうかは、この定義のようなものです。

タイプのフィールドとメソッドの第二に、アクセス変数/プロパティ

アクセス変数またはプロパティの種類、の使用

Expression.Property()

アクセス変数/属性または使用されるタイプのフィールド

Expression.PropertyOrField()

アクセス変数やメソッドの種類、

Expression.Call()

アクセス属性フィールドとメソッド

Expression.MakeMemberAccess

彼らはMemberExpression型を返します。

使用は、/ NOインスタンスをインスタンス化しないようによれば、小さな差がある、または上型変数と述べました。

手段、参照型の値型またはインスタンスを定義して、それは可変です。

型、参照型を指し、静的タイプ属性フィールドまたは静的/メソッドがインスタンス化されるべきではありません。

上記の説明は厳格ではない、次の例では、ゆっくりと説明します。

1.アクセスプロパティ

使用Expression.Property()またはExpression.PropertyOrField()プロパティを呼び出します。

静的な型の属性を呼び出し

コンソールが静的に型付けされ、Console.Titleは、コンパイラプログラムの実際の位置を得ることができます。

            Console.WriteLine(Console.Title);

式ツリーを使用して、以下のように表現さ

            MemberExpression member = Expression.Property(null, typeof(Console).GetProperty("Title"));
            Expression<Func<string>> lambda = Expression.Lambda<Func<string>>(member);

            string result = lambda.Compile()();
            Console.WriteLine(result);

            Console.ReadKey();

呼び出しは、プロパティの静的な型なので、最初のパラメータが空であるため。

2番目のパラメータはタイプPropertyInfoです。

呼び出しプロパティ/フィールドの例

以下のC#コード

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

式ツリーでは、プロパティのインスタンスを起動します

            ParameterExpression a = Expression.Parameter(typeof(List<int>), "a");
            MemberExpression member = Expression.Property(a, "Count");

            Expression<Func<List<int>, int>> lambda = Expression.Lambda<Func<List<int>, int>>(member, a);
            int result = lambda.Compile()(new List<int> { 1, 2, 3 });
            Console.WriteLine(result);

            Console.ReadKey();

Expression.Property()、自分自身をテストするための他の方法に加えて、ここではそれらを繰り返すありません。

2.コール機能

使用して、Expression.Call()関数または関数の静的な型のインスタンスを呼び出すことができます。

関数の静的な型を呼び出します

コンソールでは、たとえば、WriteLineメソッド()メソッドを呼び出します

            Console.WriteLine("调用WriteLine方法");

            MethodCallExpression method = Expression.Call(
                null,
                typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }),
                Expression.Constant("调用WriteLine方法"));

            Expression<Action> lambda = Expression.Lambda<Action>(method);
            lambda.Compile()();
            Console.ReadKey();

Expression.Call()メソッドをリロードする方法がより一般的に使用されるオーバーロードされています

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

最初のインスタンスがnullであるので、関数の静的な型をコールするので(英語のインスタンスのインスタンスを意味します)。

第二の方法は、呼び出すメソッドをオーバーロードされています。

最後の引数が渡されたパラメータです。

関数呼び出しの例

クラスを書きます

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

printf()メソッドを呼び出すの例

            Test test = new Test();
            test.Print("打印出来");
            Console.ReadKey();

次のように表現表現

            ParameterExpression a = Expression.Variable(typeof(Test), "test");

            MethodCallExpression method = Expression.Call(
                a,
                typeof(Test).GetMethod("Print", new Type[] { typeof(string) }),
                Expression.Constant("打印出来")
                );

            Expression<Action<Test>> lambda = Expression.Lambda<Action<Test>>(method,a);
            lambda.Compile()(new Test());
            Console.ReadKey();

ことに注意してくださいExpression.Variable(typeof(Test), "test");変数の定義だけが、/割り当てを初期化されていません。参照型の場合、インスタンス化する必要があります。

上記の方法は、外の世界は、着信内部の例を通して、式の中でインスタンス化する方法を言うようになっています。

第三に、参照型のインスタンス化

その後、参照のタイプの例として、新新の使用、および適切なコンストラクタ呼び出しを選択するには、プロパティの値を設定します。

さて、上記の手順に従って、我々は個別に説明しました。

新着

使用するExpression.New()タイプのコンストラクタを呼び出すために。

彼は5ヘビーデューティー、ヘビーデューティーを持っていた、一般的に使用される2があります。

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

依然として上記の試験タイプを使用

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

デフォルトコンストラクタは、パラメータ、または唯一のコンストラクタを持っていないので、上記のように呼び出します。

あなたはコンストラクタを指定したい場合、次のことができます

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

ここでは詳細に説明されていません。

それらを割り当てます

コンストラクタしばらくの例としては、属性に割り当てることができます。

        public static MemberInitExpression MemberInit(NewExpression newExpression, IEnumerable<MemberBinding> bindings);

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

オーバーロードされた二つは同じです。

私たちは、テストクラスを変更します

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

それから

            var binding = Expression.Bind(
                typeof(Test).GetMember("sample")[0],
                Expression.Constant(10)
            );

参照型を作成します。

Expression.MemberInit()

これは、コンストラクタを呼び出し、新しいオブジェクトの1つ以上のメンバーを初期化表します。

クラスのインスタンスであれば、使用することができます

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

あなたは、インスタンス生成時にメンバーに割り当てる場合

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

            // 给 Test 类型的一个成员赋值
            var binding = Expression.Bind(
                typeof(Test).GetMember("sample")[0],Expression.Constant(10));

            MemberInitExpression test = Expression.MemberInit(newA,
                new List<MemberBinding>() { binding}
                );

コールのタイプコンストラクタの例として、メンバーに割り当て、次のサンプルコード

            // 调用构造函数
            NewExpression newA = Expression.New(typeof(Test));

            // 给 Test 类型的一个成员赋值
            var binding = Expression.Bind(
                typeof(Test).GetMember("sample")[0], Expression.Constant(10));

            // 实例化一个类型
            MemberInitExpression test = Expression.MemberInit(newA,
                new List<MemberBinding>() { binding }
                );

            // 调用方法
            MethodCallExpression method1 = Expression.Call(
                test,
                typeof(Test).GetMethod("Print", new Type[] { typeof(string) }),
                Expression.Constant("打印出来")
                );

            // 调用属性
            MemberExpression method2 = Expression.Property(test, "sample");

            Expression<Action> lambda1 = Expression.Lambda<Action>(method1);
            lambda1.Compile()();

            Expression<Func<int>> lambda2 = Expression.Lambda<Func<int>>(method2);
            int sample = lambda2.Compile()();
            Console.WriteLine(sample);

            Console.ReadKey();

呼び出すためにジェネリック型をインスタンス化し、第四

テストクラスは、このように変更し

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

Testクラスはジェネリッククラスは、模範的なインスタンス生成式を持ってい

        static void Main(string[] args)
        {
            RunExpression<string>();
            Console.ReadKey();
        }
        public static void RunExpression<T>()
        {
            // 调用构造函数
            NewExpression newA = Expression.New(typeof(Test<T>));

            // 实例化一个类型
            MemberInitExpression test = Expression.MemberInit(newA,
                new List<MemberBinding>() { }
                );

            // 调用方法
            MethodCallExpression method = Expression.Call(
                test,
                typeof(Test<T>).GetMethod("Print").MakeGenericMethod(new Type[] { typeof(T) }),
                Expression.Constant("打印出来")
                );

            Expression<Action> lambda1 = Expression.Lambda<Action>(method);
            lambda1.Compile()();

            Console.ReadKey();
        }

第五に、変数のセットの定義は、初期設定では、要素を追加します

コレクション型を使用しListInitExpression表現します。

コレクション型を作成し、必要に

IEnumerableをコレクションアイテムを設定する単一要素の初期値をElementInit。

コレクションを初期化しListInit。

C#は、私たちはIEnumerableをコレクションを達成した、セットはアルトメソッドやプロパティを追加しています。

添加元素の集合をC#を使用して初期化することは、それがあってもよいです

            List<string> list = new List<string>()
            {
                "a",
                "b"
            };
            list.Add("666");

ElementInit /添加元素によって初期化するために、Addメソッドを呼び出している式ツリーで。

            MethodInfo listAdd = typeof(List<string>).GetMethod("Add");

            /*
             * new List<string>()
             * {
             *     "a",
             *     "b"
             * };
             */
            ElementInit add1 = Expression.ElementInit(
                listAdd,
                Expression.Constant("a"),
                Expression.Constant("b")
                );
            // Add("666")
            ElementInit add2 = Expression.ElementInit(listAdd, Expression.Constant("666"));

            MethodInfo listAdd = typeof(List<string>).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<string>));

            // 初始化值
            ListInitExpression setList = Expression.ListInit(
                list,
                add1,
                add2,
                add3
                );
            // 没啥执行的,就这样看看输出的信息
            Console.WriteLine(setList.ToString());

            MemberExpression member = Expression.Property(setList, "Count");

            Expression<Func<int>> lambda = Expression.Lambda<Func<int>>(member);
            int result = lambda.Compile()();
            Console.WriteLine(result);

            Console.ReadKey();

おすすめ

転載: www.cnblogs.com/whuanle/p/11569083.html