• 动态代码的使用(反射和动态生成类)


    动态代码的使用(反射和动态生成类)
        在软件开发尤其是框架和底层开发时,为了更灵活的控制代码,常常需要进行一些动态的操作。比如根

    据用户的输入等动态的调用类中的方法或者根据数据库表结 构、用户要求动态的生成一些类,然后再动态

    的调用类中的方法。当然使用这些方式时会对性能有一点影响,具体使用过程中可以根据实际情况来定,不

    过一般的 B/S开发中主要的瓶颈还是在数据库操作和网速方面,这点影响应该可以忽略的

        一、反射的使用
        可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。然后,可以

    调用类型的方法或访问其字段和属性。
        需要使用的命名空间:System.Reflection
        反射的作用很多,下面的例子主要是看一下怎么动态的调用类中的方法。
        例子类


        class ReflTest1
        {
            private string _prop1;

            public string Prop1
            {
                get { return _prop1; }
                set { _prop1 = value; }
            }

            public void Write1(string strText)
            {
                Console.WriteLine("111111111:" + strText);
            }
            public void Write2(string strText)
            {
                Console.WriteLine("222222222:" + strText);
            }
            public void MyWrite(string strText)
            {
                Console.WriteLine("3333333333:" + strText);
            }
        }

    这个例子中提供了三个方法和一个属性,下面的代码来动态的调用它们:


                string strText = "abcd";

                BindingFlags flags = (BindingFlags.NonPublic | BindingFlags.Public |
                    BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly);

                Type t = typeof(ReflTest1);
                MethodInfo[] mi = t.GetMethods(flags);
                Object obj = Activator.CreateInstance(t);

                foreach (MethodInfo m in mi)
                {
                    if (m.Name.StartsWith("Write"))
                    {
                        m.Invoke(obj, new object[] { strText });
                    } [Page]
                }

                MethodInfo mMy = t.GetMethod("MyWrite");
                if (mMy != null)
                {
                    mMy.Invoke(obj, new object[] { strText });
                }

        BindingFlags用来设置要取得哪些类型的方法,然后我们就可以取得这些方法来动态的调用。(当然为

    了可以循环的调用方法,在方法的命名方面可以自己指定一个规则)


        二、动态生成类
        我们可以在程序运行过程中调用.NET中提供的编译类,动态的将一段string编译成一个类,然后再通过

    反射来调用它
        需要使用的命名空间:System.CodeDom System.CodeDom.Compiler Microsoft.CSharp

    System.Reflection

        动态创建、编译类的代码如下:


            public static Assembly NewAssembly()
            {
                //创建编译器实例。
                provider = new CSharpCodeProvider();
                //设置编译参数。
                paras = new CompilerParameters();
                paras.GenerateExecutable = false;
                paras.GenerateInMemory = true;

                //创建动态代码。
                StringBuilder classSource = new StringBuilder();
                classSource.Append("public   class   DynamicClass \n");
                classSource.Append("{\n");

                //创建属性。
                classSource.Append(propertyString("aaa"));
                classSource.Append(propertyString("bbb"));
                classSource.Append(propertyString("ccc"));

                classSource.Append("}");

                System.Diagnostics.Debug.WriteLine(classSource.ToString());

                //编译代码。
                CompilerResults result = provider.CompileAssemblyFromSource(paras,

    classSource.ToString());

                //获取编译后的程序集。
                Assembly assembly = result.CompiledAssembly; [Page]

                return assembly;
            }

            private static string propertyString(string propertyName)
            {
                StringBuilder sbProperty = new StringBuilder();
                sbProperty.Append(" private   int   _" + propertyName + "   =   0;\n");
                sbProperty.Append(" public   int   " + "" + propertyName + "\n");
                sbProperty.Append(" {\n");
                sbProperty.Append(" get{   return   _" + propertyName + ";}   \n");
                sbProperty.Append(" set{   _" + propertyName + "   =   value;   }\n");
                sbProperty.Append(" }");
                return sbProperty.ToString();
            }

    propertyString方法就是用来拼写字符串的
        整个代码比较简单,主要步骤就是:1、拼写类的字符串  2、调用CSharpCodeProvider类进行编译得到

    程序集(assembly)


        接下来就可以利用之前反射的方法来动态调用这个类中的属性了:


                Assembly assembly = NewAssembly();

                object Class1 = assembly.CreateInstance("DynamicClass");
                ReflectionSetProperty(Class1, "aaa", 10);
              
                ReflectionGetProperty(Class1, "aaa");

                object Class2 = assembly.CreateInstance("DynamicClass");
                ReflectionSetProperty(Class1, "bbb", 20);
                ReflectionGetProperty(Class1, "bbb");

        DynamicClass是我动态类的类名,aaa和bbb是其中的属性
        ReflectionSetProperty和ReflectionGetProperty代码如下:
        给属性赋值


            private static void ReflectionSetProperty(object objClass, string propertyName, int

    value)
            {
                PropertyInfo[] infos = objClass.GetType().GetProperties();
                foreach (PropertyInfo info in infos)
                {
                    if (info.Name == propertyName && info.CanWrite) [Page]
                    {
                        info.SetValue(objClass, value, null);
                    }
                }
            }
        取得属性的值
            private static void ReflectionGetProperty(object objClass, string propertyName)
            {
                PropertyInfo[] infos = objClass.GetType().GetProperties();
                foreach (PropertyInfo info in infos)
                {
                    if (info.Name == propertyName && info.CanRead)
                    {
                        System.Console.WriteLine(info.GetValue(objClass, null));
                    }
                }
            }

    添加自定义的dll和命名空间,注意要绝对路径(系统本身的不用,不过codedom的版本要对上,比如2005的codedom加linq的dll还是要绝对路径),至于怎么取绝对路径,自己来吧

            CodeCompileUnit m_CodeCompileUnit = new CodeCompileUnit();
            CodeNamespace m_CodeNameSpace = new CodeNamespace("xml.tables");

            m_CodeCompileUnit.ReferencedAssemblies.Add(@"E:\本地测试\动态生成代码\动态生成代码\Bin\RDll.dll");
            m_CodeNameSpace.Imports.Add(new System.CodeDom.CodeNamespaceImport("RDll"));

  • 相关阅读:
    【bzoj3676】[Apio2014]回文串 —— 回文自动机的学习
    树链剖分求LCA
    读入输出优化
    【bzoj3124】[Sdoi2013]直径
    【codevs2183】匹配字符串
    【codevs2011】【LNOI2013】最小距离之和
    【codevs1306】广播操的游戏
    【hdu3966】Aragorn's Story
    【hdu3518】Boring counting
    C++-HDU3400-Line belt[三分]
  • 原文地址:https://www.cnblogs.com/cuihongyu3503319/p/1622835.html
Copyright © 2020-2023  润新知