首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

使用 LINQ 運算式樹實現強型別反射

     編輯:關於.NET

傳統反射以字串指定成員名稱,重構時易導致執行期錯誤。LINQ 運算式樹(Expression<TDelegate>)可在編譯期檢查成員存取,實現強型別反射。

核心實作:MyReflection 輔助類別

public static class MyReflection {
    public delegate void Operation<T>(T declaringType);
    public delegate void Operation<T, A1, A2>(T declaringType, object a1, object a2);
    public delegate object OperationWithReturnValue<T>(T declaringType);

    public static MethodInfo Method<T>(Expression<Operation<T>> method) => GetMethodInfo(method);
    public static MethodInfo Method<T>(Expression<OperationWithReturnValue<T>> method) => GetMethodInfo(method);
    public static MethodInfo Method<T, A1, A2>(Expression<Operation<T, A1, A2>> method) => GetMethodInfo(method);

    private static MethodInfo GetMethodInfo(Expression method) {
        var lambda = method as LambdaExpression;
        if (lambda == null) throw new ArgumentNullException();
        MethodCallExpression callExpr = null;
        if (lambda.Body.NodeType == ExpressionType.Call)
            callExpr = lambda.Body as MethodCallExpression;
        else if (lambda.Body.NodeType == ExpressionType.Convert)
            callExpr = ((UnaryExpression)lambda.Body).Operand as MethodCallExpression;
        if (callExpr == null) throw new ArgumentException();
        return callExpr.Method;
    }
}

ExpressionType.Call 對應無傳回值方法,ExpressionType.Convert 對應有傳回值方法(因 Lambda 轉換為 Func 需轉型)。

測試類別與用法

public class MyTest {
    public void TestFunc() => Console.WriteLine("Test Function");
    public static void StaticTestFunc() => Console.WriteLine("Test Static Function");
    public int TestFuncWithReturnValue() { Console.WriteLine("Test function with return value"); return 100; }
    public void TestFuncWithArgs(string arg1, int arg2) => Console.WriteLine($"Test function with arguments [{arg1},{arg2}]");
}

// 使用方式
var mi = MyReflection.Method<MyTest>(m => m.TestFunc());
mi.Invoke(new MyTest(), null);

mi = MyReflection.Method<MyTest>(m => MyTest.StaticTestFunc());
mi.Invoke(null, null);

mi = MyReflection.Method<MyTest>(m => m.TestFuncWithReturnValue());
Console.WriteLine("Return value: {0}", mi.Invoke(new MyTest(), null));

mi = MyReflection.Method<MyTest, object, object>((m, x, y) => m.TestFuncWithArgs((string)x, (int)y));
mi.Invoke(new MyTest(), new object[] { "Argument1", 50 });

優缺點分析

  • 優點:編譯期檢查成員簽名,避免執行期例外;重構友善。
  • 缺點:不同簽名需對應不同委託型別;運算式樹建構效率較低,視情況取捨。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved