zoukankan      html  css  js  c++  java
  • 动态代码的使用(反射和动态生成类)

    在软件开发尤其是框架和底层开发时,为了更灵活的控制代码,常常需要进行一些动态的操作。比如根据用户的输入等动态的调用类中的方法或者根据数据库表结构、用户要求动态的生成一些类,然后再动态的调用类中的方法。当然使用这些方式时会对性能有一点影响,具体使用过程中可以根据实际情况来定,不过一般的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 });
                    }
                }

                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;

    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)
    {
                        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));
                    }
                }
            }

  • 相关阅读:
    linux杀死僵尸进程
    通过dd命令显示硬盘的读写性能
    linux 压缩与解压缩
    linux云主机cpu一直很高降不下来,系统日志报nf_conntrack: table full, dropping packet.
    vsftp配置文件详解
    linux中ping带时间及打印内容到文件
    atop工具检测linux硬件异常
    windows连接服务端的域名正常,linux却不通,(针对于负载均衡后端节点设置)
    有你的地方就是天堂
    Java 异常 —— java.io.InvalidClassException: javax.xml.namespace.QName; local class incompatible
  • 原文地址:https://www.cnblogs.com/bennylam/p/1750770.html
Copyright © 2011-2022 走看看