使用Linq實現強型別反射

來源:互聯網
上載者:User

  今天無意中看到這一篇文章Linq beyond queries: strong-typed reflection,發現Linq除了查詢還可以用於其它方面,這篇文章裡面主要介紹了如何通過Linq來實現強型別的反射。

  通常在使用反射的時候,如果不小心把方法名稱寫錯或者參數類型不符,運行時就會拋出異常。一般來說我們會這樣寫代碼來獲得MethodInfo:

 MethodInfo mi = typeof(MyTest).GetMethod("TestFunc",new Type[]{ typeof(string), typeof(int)});

 如果對MyTest類進行重構,改變了方法的名稱或者參數類型等,運行時肯定會出現異常,因為這些錯誤在編譯期間是檢查不出來的。如果項目中大量使用了反射,無疑一點改動就會引發潛在的問題。 現在出現了Linq,通過Lambda運算式樹狀架構可以實現強型別反射。下面是我仿照它的例子寫的測試代碼,因為現在的API有了一些改動,具體的介紹可以看原文:

 public 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)     {         return GetMethodInfo(method);     }     public static MethodInfo Method<T>(Expression<OperationWithReturnValue<T>> method)     {         return GetMethodInfo(method);     }     public static MethodInfo Method<T, A1, A2>(Expression<Operation<T, A1, A2>> method)     {         return GetMethodInfo(method);     }     private static MethodInfo GetMethodInfo(Expression method)     {         LambdaExpression lambda = method as LambdaExpression;         if (lambda == null)             throw new ArgumentNullException();         MethodCallExpression methodExpr = null;         if (lambda.Body.NodeType == ExpressionType.Call)             methodExpr = lambda.Body as MethodCallExpression;         else if (lambda.Body.NodeType == ExpressionType.Convert)             methodExpr = ((UnaryExpression)lambda.Body).Operand as MethodCallExpression;         if (methodExpr == null)             throw new ArgumentException();         return methodExpr.Method;     } }

 首先建立了三個delegate,用來委託我們自己定義的方法。這裡也可以使用Func,不過Func要求有傳回值,不能委託無傳回值的方法。代碼很簡單,有一點值得注意的是ExpressionType.Call表示無傳回值的方法,ExpressionType.Convert表示有傳回值的方法。

 下面是一個測試類別:

 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 [{0},{1}]", arg1, arg2.ToString());     } }

最後看看怎樣使用:

 MethodInfo 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 from TestFuncWithReturnValue is {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 });

 輸出結果為:

使用強型別反射的好處是編譯器檢查,如果方法簽名不匹配就會報錯,避免了運行時拋出異常。當然它也有不足,不同的方法簽名對應一個相應簽名的delegate,而且這樣的實現效率很低,因為使用了運算式樹狀架構等,只能根據需要進行取捨了。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.