• .net各版本反射多种方法介绍


           本文主要以CSharp语言为主,首先假设这样简单的CLASS为示例:

       1:      public class Person
       2:      {
       3:          public void Action()
       4:          {
       5:              Console.WriteLine("Run");
       6:          }
       7:      }

            在.net framework 1.1 到2.0 下,我们用CSharp常规反射调用Action方法如下:

       1:          [Test]
       2:          public void TestGeneral()
       3:          {
       4:              var p = new Person();
       5:              Type t = p.GetType();
       6:              var m = t.GetMethod("Action", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
       7:              m.Invoke(p, null);
       8:          }

        使用Delegate,在多次调用下 更高效:

       1:          [Test]
       2:          public void TestReflectionWithDelegate()
       3:          {
       4:              var p = new Person();
       5:              Type t = p.GetType();
       6:              var actionmethod = (Action)Delegate.CreateDelegate(typeof(Action), p, "Action");
       7:              actionmethod();
       8:          }

         然后还可使用IL Emit来实现,DynamicMethod, 关于Emit你可以去MSDN了解,以及<<C# 4.0 in a Nutshell>>书有介绍.

       1:          [Test]
       2:          public void TestReflectionWithEmit()
       3:          {
       4:              var methodinfo = typeof(Person).GetMethod("Action", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
       5:              DynamicMethod method = new DynamicMethod("Action2", null, null);
       6:              ILGenerator ilGenerator = method.GetILGenerator();
       7:   
       8:              ConstructorInfo ci = typeof(Person).GetConstructor(new Type[0]);
       9:              ilGenerator.Emit(OpCodes.Newobj, ci);
      10:              ilGenerator.EmitCall(OpCodes.Call, methodinfo, null);
      11:              ilGenerator.Emit(OpCodes.Ret);
      12:   
      13:              var runmethod = (Action)method.CreateDelegate(typeof(Action));
      14:              runmethod();
      15:          }

          到.net 3.0 以后,我们可以使用Expression Tree来实现,这里直接使用了是DynamicMethodExecutor,参考老赵的文章,这样更加简洁

       1:          [Test]
       2:          public void TestReflectionWithLinqExpression()
       3:          {
       4:              var methodInfo = typeof(Person).GetMethod("Action", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
       5:              var executor = new DynamicMethodExecutor(methodInfo);
       6:   
       7:              var p = new Person();
       8:              executor.Execute(p, null);
       9:          }

     

        DynamicMethodExecutor类

     public class DynamicMethodExecutor
        {
            private Func<object, object[], object> m_execute;
     
            public DynamicMethodExecutor(MethodInfo methodInfo)
            {
                this.m_execute = this.GetExecuteDelegate(methodInfo);
            }
     
            public object Execute(object instance, object[] parameters)
            {
                return this.m_execute(instance, parameters);
            }
     
            private Func<object, object[], object> GetExecuteDelegate(MethodInfo methodInfo)
            {
                // parameters to execute
                ParameterExpression instanceParameter = Expression.Parameter(typeof(object), "instance");
                ParameterExpression parametersParameter = Expression.Parameter(typeof(object[]), "parameters");
     
                // build parameter list
                List<Expression> parameterExpressions = new List<Expression>();
                ParameterInfo[] paramInfos = methodInfo.GetParameters();
                for (int i = 0; i < paramInfos.Length; i++)
                {
                    // (Ti)parameters[i]
                    BinaryExpression valueObj = Expression.ArrayIndex(parametersParameter, Expression.Constant(i));
                    UnaryExpression valueCast = Expression.Convert(valueObj, paramInfos[i].ParameterType);
     
                    parameterExpressions.Add(valueCast);
                }
     
                // non-instance for static method, or ((TInstance)instance)
                Expression instanceCast = methodInfo.IsStatic ? null : Expression.Convert(instanceParameter, methodInfo.ReflectedType);
     
                // static invoke or ((TInstance)instance).Method
                MethodCallExpression methodCall = Expression.Call(instanceCast, methodInfo, parameterExpressions);
     
                // ((TInstance)instance).Method((T0)parameters[0], (T1)parameters[1], ...)
                if (methodCall.Type == typeof(void))
                {
                    Expression<Action<object, object[]>> lambda =
                        Expression.Lambda<Action<object, object[]>>(
                            methodCall, instanceParameter, parametersParameter);
     
                    Action<object, object[]> execute = lambda.Compile();
                    return (instance, parameters) =>
                    {
                        execute(instance, parameters);
                        return null;
                    };
                }
                else
                {
                    UnaryExpression castMethodCall = Expression.Convert(
                        methodCall, typeof(object));
                    Expression<Func<object, object[], object>> lambda =
                        Expression.Lambda<Func<object, object[], object>>(
                            castMethodCall, instanceParameter, parametersParameter);
     
                    return lambda.Compile();
                }
            }
     
        }

          到.net 4.0有DLR,CSharp多了dynamic关键字,很多工作交给编译器去做了,代码更多简洁:

       1:          [Test]
       2:          public void TestReflectionWithDynamic()
       3:          {
       4:              dynamic p = new Person();
       5:              p.Action();
       6:          }

          这时在VS中使用dynamic,这时成员是没有智能提示的。这里我们反射的成员是public,当你遇到private在dynamic,将会有这样的exception:
    “…inaccessible due to its protection level” ,当然也有办法你可以参考这篇文章。所有UnitTest都输出同样的结果。

         希望这篇POST对您开发有帮助。


    作者:Petter Liu
    出处:http://www.cnblogs.com/wintersun/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
    该文章也同时发布在我的独立博客中-Petter Liu Blog

  • 相关阅读:
    Java学习-IO流-read()和write()详解
    JAVA中String类常用构造方法
    java的System.exit(0)和System.exit(1)区别。
    Eclipse快捷键大全
    Java Arraylist的遍历
    Java Map的遍历
    C++求最大公约数,最小公倍数
    C++sort使用实例
    [Project Euler] 题目汇总
    [leetcode]做过的题的目录
  • 原文地址:https://www.cnblogs.com/wintersun/p/2028777.html
Copyright © 2020-2023  润新知