亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C#值類型、引用類型、泛型、集合的表達式樹怎么創建

發布時間:2022-01-18 16:39:28 來源:億速云 閱讀:148 作者:iii 欄目:開發技術

這篇文章主要介紹了C#值類型、引用類型、泛型、集合的表達式樹怎么創建的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇C#值類型、引用類型、泛型、集合的表達式樹怎么創建文章都會有所收獲,下面我們一起來看看吧。

    一,定義變量

    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 允許 Ref, Variable 不允許。

    筆者在官方文檔和其他作者文章上,都沒有找到具體區別是啥,去 stackoverflow 搜索和查看源代碼后,確定他們的區別在于 Variable 不能使用 ref 類型。

    從字面意思來看,聲明一個變量,應該用Expression.Variable, 函數的傳入參數應該使用Expression.Parameter

    無論值類型還是引用類型,都是這樣子定義。

    二,訪問變量/類型的屬性字段和方法

    訪問變量或類型的屬性,使用

    Expression.Property()

    訪問變量/類型的屬性或字段,使用

    Expression.PropertyOrField()

    訪問變量或類型的方法,使用

    Expression.Call()

    訪問屬性字段和方法

    Expression.MakeMemberAccess

    他們都返回一個 MemberExpression類型。

    使用上,根據實例化/不實例化,有個小區別,上面說了變量或類型。

    意思是,已經定義的值類型或實例化的引用類型,是變量;

    類型,就是指引用類型,不需要實例化的靜態類型或者靜態屬性字段/方法。

    上面的解釋不太嚴謹,下面示例會慢慢解釋。

    1. 訪問屬性

    使用 Expression.Property() 或 Expression.PropertyOrField()調用屬性。

    調用靜態類型屬性

    Console 是一個靜態類型,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();

    因為調用的是靜態類型的屬性,所以第一個參數為空。

    第二個參數是一個 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() 可以調用一個靜態類型的函數或者實例的函數。

    調用靜態類型的函數

    以 Console 為例,調用 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)

    因為要調用靜態類型的函數,所以第一個 instance 為空(instance英文意思是實例)。

    第二個 method 是要調用的重載方法。

    最后一個 arguments 是傳入的參數。

    調用實例的函數

    寫一個類

        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"); 僅定義了一個變量,還沒有初始化/賦值。對于引用類型來說,需要實例化。

    上面的方式,是通過外界實例化傳入里面的,后面會說如何在表達式內實例化。

    三,實例化引用類型

    引用類型的實例化,使用 new ,然后選擇調用合適的構造函數、設置屬性的值。

    那么,根據上面的步驟,我們分開討論。

    new

    使用 Expression.New()來調用一個類型的構造函數。

    他有五個重載,有兩種常用重載:

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

    依然使用上面的 Test 類型

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

    兩種重載是一樣的。

    我們將 Test 類改成

        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()

    表示調用構造函數并初始化新對象的一個或多個成員。

    如果實例化一個類,可以使用

                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&lt;MemberBinding&gt;() { 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();

    四,實例化泛型類型于調用

    將 Test 類,改成這樣

        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表示。

    創建集合類型,需要使用到

    ElementInit 表示 IEnumerable集合的單個元素的初始值設定項。

    ListInit 初始化一個集合。

    C# 中,集合都實現了 IEnumerable,集合都具有 Add 扥方法或屬性。

    使用 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();

    關于“C#值類型、引用類型、泛型、集合的表達式樹怎么創建”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“C#值類型、引用類型、泛型、集合的表達式樹怎么創建”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    瓮安县| 田林县| 民乐县| 桑植县| 威信县| 安西县| 南郑县| 新野县| 昌黎县| 江永县| 清苑县| 瓮安县| 响水县| 衡阳市| 盈江县| 大城县| 江阴市| 公安县| 文登市| 安丘市| 铜川市| 赤水市| 澄江县| 台江县| 德庆县| 吉首市| 鄄城县| 桦南县| 民丰县| 成都市| 长宁区| 依安县| 眉山市| 滁州市| 女性| 江川县| 平和县| 长阳| 京山县| 富川| 常熟市|