程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 使用Linq實現強類型反射

使用Linq實現強類型反射

編輯:關於.NET

今天無意中看到這一篇文章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,而且這樣的實現效率很低,因為使用了表 達式樹等,只能根據需要進行取捨了。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved