zoukankan      html  css  js  c++  java
  • 反射发送实战-InvokeMember 转

    反射是.net中的高级功能之一,利用反射可以实现许多以前看来匪夷所思的功能,下面是我看了《Programming C#》(O'Reilly)之后对于反射的一点实践,本想直接做个应用程序来说明问题,但苦于工作繁忙并考虑到以简单为主,故先对反射发送(reflection emit)的使用做一些介绍。文章最后再给出一个实例。
    下面的程序在运行时生成了一个Test.cs文件,并调用csc编译成Test.dll文件,然后利用Type.InvokeMember()方法调用其中的SayHello()方法,然后和原始方法对比一下性能。
    using System;
    using System.Diagnostics;
    using System.IO;
    using System.Reflection;
    namespace InvokeMember
    {
    ///
    /// Class1 的摘要说明。
    ///

    class Class1 { ///
    /// 应用程序的主入口点。
    ///

    [STAThread]
    static void Main(string[] args)
    {
    //循环次数
    const int iterations = 100;
    //计算所用时间
    DateTime startTime = DateTime.Now;
    for(int i = 0;i< iterations;i++) { //对照方法
    Console.WriteLine("Hello,World");
    }
    TimeSpan elasped = DateTime.Now - startTime;
    Console.WriteLine("Looping Elapsed milliseconds:" + elasped.TotalMilliseconds + "for {0} iterations",iterations);

    //使用反射发送
    ReflectionTest t = new ReflectionTest();
    //计算所用时间
    startTime = DateTime.Now;
    for(int i = 0;i < iterations;i++)
    {
    t.DoOperation();
    }
    elasped = DateTime.Now - startTime;
    Console.WriteLine("Looping Elapsed milliseconds:" + elasped.TotalMilliseconds + "for {0} iterations",iterations);
    Console.ReadLine();
    }
    }
    ///
    /// Reflection 的摘要说明。
    ///

    public class ReflectionTest
    {
    //保存动态生成并编译的类的type对象
    Type theType = null;
    //保存动态生成类的实例
    object theClass = null;
    ///
    /// 供Client调用的方法
    ///

    public void DoOperation()
    {
    //未初始化
    if(theType == null)
    {
    //初始化
    GenerateCode();
    }
    //调用方法时的参数数组(此处为空)
    object[] arguments = new object[0];
    //调用动态生成类的方法
    theType.InvokeMember("SayHello",//要调用的方法名
    BindingFlags.Default|BindingFlags.InvokeMethod,//Binding标志,具体参看msdn
    null,//使用默认Binding对象
    theClass,//在theClass实例上调用此方法
    arguments//调用方法时的参数数组
    );
    }
    ///
    /// 运行时生成代码
    ///

    private void GenerateCode()
    {
    //文件名
    string fileName = "Test";
    //打开文件,如果不存在,则创建
    Stream s = File.Open(fileName + ".cs",FileMode.Create);
    //创建一个StreamWriter来写入数据
    StreamWriter wrtr = new StreamWriter(s);
    //写入动态创建类的源代码
    wrtr.WriteLine("// 动态创建Test类");
    //类名
    string className = "TestClass";
    wrtr.WriteLine("using System;");
    wrtr.WriteLine("class {0}",className);
    wrtr.WriteLine("{");
    wrtr.WriteLine("\tpublic void SayHello()");
    wrtr.WriteLine("\t{");
    wrtr.WriteLine("\t\tConsole.WriteLine(\"Hello,World\");");
    wrtr.WriteLine("\t}");
    wrtr.WriteLine("}");
    //关闭StreamWriter和文件
    wrtr.Close();
    s.Close();
    //启动进程编译源文件
    //指定参数
    ProcessStartInfo psi = new ProcessStartInfo();
    //启动cmd.exe
    psi.FileName = "cmd.exe";
    //cmd.exe的参数,/c-close,完成后关闭;后为参数,指定cmd.exe使用csc来编译刚才生成的源文件
    string compileString = "/c C:\\WINNT\\Microsoft.NET\\Framework\\v1.1.4322\\csc.exe /optimize+ /target:library {0}.cs";
    psi.Arguments = String.Format(compileString,fileName);
    //运行时的风格-最小化
    psi.WindowStyle = ProcessWindowStyle.Minimized;
    //启动进程
    Process proc = Process.Start(psi);
    //指定当前在此进程退出前等待
    proc.WaitForExit();
    //从编译好的dll文件load一个Assembly
    Assembly a = Assembly.LoadFrom(fileName + ".dll");
    //创建类的实例
    theClass = a.CreateInstance(className);
    //取得此类实例的类型
    theType = a.GetType(className);
    //删除源文件
    //File.Delete(flieName + ".cs");
    }
    }}

    最后贴一个BindingFlags的Demo Share with EveryOne
    -----------------------------------------------
    using System;
    using System.Reflection;
    using System.IO;

    namespace BindingFlagsSnippet
    {
        class EntryPoint
        {
            static void Main(string[] args)
            {
                Invoke.Go();
            }
        }

       
        class Invoke
        {
            public static void Go()
            {
                // BindingFlags.InvokeMethod
                // Call a static method.
                Type t = typeof (TestClass);

                Console.WriteLine();
                Console.WriteLine("Invoking a static method.");
                Console.WriteLine("-------------------------");
                t.InvokeMember ("SayHello", BindingFlags.InvokeMethod, null, null, new object [] {});

                // BindingFlags.InvokeMethod
                // Call an instance method.
                TestClass c = new TestClass ();
                Console.WriteLine();
                Console.WriteLine("Invoking an instance method.");
                Console.WriteLine("----------------------------");
                c.GetType().InvokeMember ("AddUp", BindingFlags.InvokeMethod, null, c, new object [] {});
                c.GetType().InvokeMember ("AddUp", BindingFlags.InvokeMethod, null, c, new object [] {});
               
                // BindingFlags.InvokeMethod
                // Call a method with parameters.
                object [] args = new object [] {100.09, 184.45};
                object result;
                Console.WriteLine();
                Console.WriteLine("Invoking a method with parameters.");
                Console.WriteLine("---------------------------------");
                result = t.InvokeMember ("ComputeSum", BindingFlags.InvokeMethod, null, null, args);
                Console.WriteLine ("{0} + {1} = {2}", args[0], args[1], result);

                // BindingFlags.GetField, SetField
                Console.WriteLine();
                Console.WriteLine("Invoking a field (getting and setting.)");
                Console.WriteLine("--------------------------------------");
                // Get a field value.
                result = t.InvokeMember ("Name", BindingFlags.GetField, null, c, new object [] {});
                Console.WriteLine ("Name == {0}", result);
                // Set a field.
                t.InvokeMember ("Name", BindingFlags.SetField, null, c, new object [] {"NewName"});
                result = t.InvokeMember ("Name", BindingFlags.GetField, null, c, new object [] {});
                Console.WriteLine ("Name == {0}", result);
               
                Console.WriteLine();
                Console.WriteLine("Invoking an indexed property (getting and setting.)");
                Console.WriteLine("--------------------------------------------------");
                // BindingFlags.GetProperty
                // Get an indexed property value.
                int  index = 3;
                result = t.InvokeMember ("Item", BindingFlags.GetProperty, null, c, new object [] {index});
                Console.WriteLine ("Item[{0}] == {1}", index, result);
                // BindingFlags.SetProperty
                // Set an indexed property value.
                index = 3;
                t.InvokeMember ("Item", BindingFlags.SetProperty, null, c, new object [] {index, "NewValue"});
                result = t.InvokeMember ("Item", BindingFlags.GetProperty , null, c, new object [] {index});
                Console.WriteLine ("Item[{0}] == {1}", index, result);
               
                Console.WriteLine();
                Console.WriteLine("Getting a field or property.");
                Console.WriteLine("----------------------------");
                // BindingFlags.GetField
                // Get a field or property.
                result = t.InvokeMember ("Name", BindingFlags.GetField | BindingFlags.GetProperty, null, c, new object [] {});
                Console.WriteLine ("Name == {0}", result);
                // BindingFlags.GetProperty
                result = t.InvokeMember ("Value", BindingFlags.GetField | BindingFlags.GetProperty, null, c, new object [] {});
                Console.WriteLine ("Value == {0}", result);

                Console.WriteLine();
                Console.WriteLine("Invoking a method with named parameters.");
                Console.WriteLine("---------------------------------------");
                // BindingFlags.InvokeMethod
                // Call a method using named parameters.
                object[] argValues = new object [] {"Mouse", "Micky"};
                String [] argNames = new String [] {"lastName", "firstName"};
                t.InvokeMember ("PrintName", BindingFlags.InvokeMethod, null, null, argValues, null, null, argNames);

                Console.WriteLine();
                Console.WriteLine("Invoking a default member of a type.");
                Console.WriteLine("------------------------------------");
                // BindingFlags.Default
                // Call the default member of a type.
                Type t3 = typeof (TestClass2);
                t3.InvokeMember ("", BindingFlags.InvokeMethod | BindingFlags.Default, null, new TestClass2(), new object [] {});
     
                // BindingFlags.Static, NonPublic, and Public
                // Invoking a member by reference.
                Console.WriteLine();
                Console.WriteLine("Invoking a method by reference.");
                Console.WriteLine("-------------------------------");
                MethodInfo m = t.GetMethod("Swap");
                args = new object[2];
                args[0] = 1;
                args[1] = 2;
                m.Invoke(new TestClass(),args);
                Console.WriteLine ("{0}, {1}", args[0], args[1]);
                // The string is case-sensitive.
                Type type = Type.GetType("System.String");

                // Check to see if the value is valid. If the object is null, the type does not exist.
                if (type == null)
                {
                    Console.WriteLine("Please ensure that you specify only valid types in the type field.");
                    Console.WriteLine("The type name is case-sensitive.");
                    return;
                }
                // Declare and populate the arrays to hold the information.
                // You must declare either NonPublic or Public with Static or the search will not work.
                FieldInfo [] fi = type.GetFields (BindingFlags.Static |
                    BindingFlags.NonPublic | BindingFlags.Public); 
                // BindingFlags.NonPublic
                MethodInfo [] miNonPublic = type.GetMethods (BindingFlags.Static |
                    BindingFlags.NonPublic);
                // BindingFlags.Public
                MethodInfo [] miPublic = type.GetMethods (BindingFlags.Static |
                    BindingFlags.Public);

                // Iterate through all the nonpublic methods.
                foreach (MethodInfo method in miNonPublic)
                {
                    Console.WriteLine(method);
                }
                // Iterate through all the public methods.
                foreach (MethodInfo method in miPublic)
                {
                    Console.WriteLine(method);
                }
                // Iterate through all the fields.
                foreach (FieldInfo f in fi)
                {
                    Console.WriteLine(f);
                }

                // BindingFlags.Instance
                // Call an instance method.
                TestClass tc = new TestClass ();
                Console.WriteLine();
                Console.WriteLine("Invoking an Instance method.");
                Console.WriteLine("----------------------------");
                tc.GetType().InvokeMember ("AddUp", BindingFlags.Public |
                    BindingFlags.Instance | BindingFlags.CreateInstance,
                    null, tc, new object [] {});

                // BindingFlags.CreateInstance
                // Calling and creating an instance method.
                Console.WriteLine();
                Console.WriteLine("Invoking and creating an instance method.");
                Console.WriteLine("-----------------------------------------");
                tc.GetType().InvokeMember ("AddUp", BindingFlags.Public |
                    BindingFlags.Instance | BindingFlags.CreateInstance,
                    null, tc, new object [] {});

                // BindingFlags.DeclaredOnly
                TestClass tc2 = new TestClass();
                Console.WriteLine();
                Console.WriteLine("DeclaredOnly members");
                Console.WriteLine("---------------------------------");
                System.Reflection.MemberInfo[] memInfo =
                    tc2.GetType().GetMembers(BindingFlags.DeclaredOnly);
                for(int i=0;i<memInfo.Length;i++)
                {
                    Console.WriteLine(memInfo[i].Name);
                }

                // BindingFlags.SuppressChangeType
                TestClass obj = new TestClass();
                Console.WriteLine();
                Console.WriteLine("Invoking static method - PrintName");
                Console.WriteLine("---------------------------------");
                System.Reflection.MethodInfo methInfo =
                    obj.GetType().GetMethod("PrintName");
                methInfo.Invoke(obj,BindingFlags.SuppressChangeType |
                    BindingFlags.InvokeMethod, null,new object[]
                    {"Brad","Smith"},null);

                // BindingFlags.IgnoreCase
                Console.WriteLine();
                Console.WriteLine("Using IgnoreCase and invoking the PrintName method.");
                Console.WriteLine("---------------------------------------------------");
                methInfo = obj.GetType().GetMethod("PrintName");
                methInfo.Invoke(obj,BindingFlags.IgnoreCase |
                    BindingFlags.InvokeMethod, null,new object[]
                    {"brad","smith"},null);

                // BindingFlags.IgnoreReturn
                Console.WriteLine();
                Console.WriteLine("Using IgnoreReturn and invoking the PrintName method.");
                Console.WriteLine("-----------------------------------------------------");
                methInfo = obj.GetType().GetMethod("PrintName");
                methInfo.Invoke(obj,BindingFlags.IgnoreReturn |
                    BindingFlags.InvokeMethod, null,new object[]
                    {"Brad","Smith"},null);

                // BindingFlags.OptionalParamBinding
                Console.WriteLine();
                Console.WriteLine("Using OptionalParamBinding and invoking the PrintName method.");
                Console.WriteLine("-------------------------------------------------------------");
                methInfo = obj.GetType().GetMethod("PrintName");
                methInfo.Invoke(obj,BindingFlags.OptionalParamBinding |
                    BindingFlags.InvokeMethod, null,new object[]
                    {"Brad","Smith"},null);

                // BindingFlags.ExactBinding
                Console.WriteLine();
                Console.WriteLine("Using ExactBinding and invoking the PrintName method.");
                Console.WriteLine("-----------------------------------------------------");
                methInfo = obj.GetType().GetMethod("PrintName");
                methInfo.Invoke(obj,BindingFlags.ExactBinding |
                    BindingFlags.InvokeMethod, null,new object[]
                    {"Brad","Smith"},null);
     
                // BindingFlags.FlattenHierarchy
                Console.WriteLine();
                Console.WriteLine("Using FlattenHierarchy and invoking the PrintName method.");
                Console.WriteLine("---------------------------------------------------------");
                methInfo = obj.GetType().GetMethod("PrintName");
                methInfo.Invoke(obj,BindingFlags.FlattenHierarchy |
                    BindingFlags.InvokeMethod, null,new object[]
                    {"Brad","Smith"},null);
            }
        }

        public class TestClass
        {
            public String Name;
            private Object [] values = new Object [] {0, 1,2,3,4,5,6,7,8,9};

            public Object this [int index]
            {
                get
                {
                    return values[index];
                }
                set
                {
                    values[index] = value;
                }
            }

            public Object Value
            {
                get
                {
                    return "the value";
                }
            }

            public TestClass ()
            {
                Name = "initialName";
            }

            int methodCalled = 0;

            public static void SayHello ()
            {
                Console.WriteLine ("Hello");
            }

            public void AddUp ()
            {
                methodCalled++;
                Console.WriteLine ("AddUp Called {0} times", methodCalled);
            }

            public static double ComputeSum (double d1, double d2)
            {
                return d1 + d2;
            }

            public static void PrintName (String firstName, String lastName)
            {
                Console.WriteLine ("{0},{1}", lastName,firstName);
            }

            public void PrintTime ()
            {
                Console.WriteLine (DateTime.Now);
            }

            public void Swap(ref int a, ref int b)
            {
                int x = a;
                a = b;
                b = x;
            }
        }

        [DefaultMemberAttribute ("PrintTime")]
        public class TestClass2
        {
            public void PrintTime ()
            {
                Console.WriteLine (DateTime.Now);
            }
        }
    }


  • 相关阅读:
    Servlet的生命周期
    HTTP协议简单记录
    Tomcat和JavaWeb目录和流程
    02 html 表格表单
    01 初识HTML
    Python 利用pywin32批量将doc转换成docx再读取成一行存入excel
    power bi 数据红绿灯详细用法
    Linux和Windows启动后台程序
    MySQL导出数据字典
    适用于渗透测试不同阶段的工具收集整理
  • 原文地址:https://www.cnblogs.com/nianshi/p/874420.html
Copyright © 2011-2022 走看看