C# 动态生成类

我们可以在程序运行过程中调用.NET中提供的编译类,动态的将一段string编译成一个类,然后再通过反射来调用它
需要使用的命名空间: System.CodeDom System.CodeDom.Compiler Microsoft.CSharp System.Reflection

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

 public static Type CreateDynamicType(string typeName)
        {
            //创建编译器实例。   
            CSharpCodeProvider provider = new CSharpCodeProvider();
            //设置编译参数。   
            CompilerParameters paras = new CompilerParameters();
            paras.GenerateExecutable = false;
            paras.GenerateInMemory = true;
            paras.IncludeDebugInformation = true;
            var assemblies = AppDomain.CurrentDomain.GetAssemblies().Where(x => !x.IsDynamic).Select(x => x.Location);
            paras.ReferencedAssemblies.AddRange(assemblies.ToArray());
            //创建动态代码。   
            StringBuilder classSource = new StringBuilder();
            bool containsNamespace = false;
            string newTypeName = typeName;
            if (typeName.Contains("."))
            {
                int index = typeName.LastIndexOf(".");
                newTypeName = typeName.Substring(index+1);
                classSource.Append("namespace " + typeName.Substring(0, index) + " {\n");
                containsNamespace = true;

            }
            classSource.Append(@"public   class   " + newTypeName + " \n");
            classSource.Append("{\n");

            //创建属性。   
            classSource.Append(CreatePropertyString("Prop1", "string"));
            classSource.Append(CreatePropertyString("Prop2", "int"));
            classSource.Append(CreatePropertyString("Prop3","string"));
            classSource.Append("}\n");
            if (containsNamespace)
            {
                classSource.Append("}\n");
            }
            //System.Diagnostics.Debug.WriteLine(classSource.ToString());

            //编译代码。   
            CompilerResults result = provider.CompileAssemblyFromSource(paras, classSource.ToString());
            if (result.Errors.HasErrors)
            {
                foreach (CompilerError error in result.Errors)
                {
                    Console.WriteLine(error.Line + ":" + error.ErrorText);
                }
                return null;
            }
            //获取编译后的程序集。   
            Assembly assembly = result.CompiledAssembly;
            return assembly.GetType(typeName);
        }
        private static string CreatePropertyString(string propertyName, string typeName)
        {
            StringBuilder sbProperty = new StringBuilder();
            sbProperty.Append(string.Format(" private   {0}   _{1} ;\n", typeName, propertyName));
            sbProperty.Append(string.Format(" public   {0}   {1} \n", typeName, propertyName));
            sbProperty.Append(" {\n");
            sbProperty.Append(" get{ return   _"+propertyName+";}\n");
            sbProperty.Append(" set{_"+propertyName+" = value;   }\n");
            sbProperty.Append(" }\n");
            return sbProperty.ToString();
        }
        private static void ReflectionSetProperty(object objClass, string propertyName, object value)
        {
            PropertyInfo[] infos = objClass.GetType().GetProperties();
            foreach (PropertyInfo info in infos)
            {
                if (info.Name == propertyName && info.CanWrite)
                {
                    info.SetValue(objClass, value, null);
                }
            }
        }
        private static object ReflectionGetProperty(object objClass, string propertyName)
        {
            PropertyInfo[] infos = objClass.GetType().GetProperties();
            foreach (PropertyInfo info in infos)
            {
                if (info.Name == propertyName && info.CanRead)
                {
                    object obj = info.GetValue(objClass, null);
                    return obj;
                }
            }
            return null;
        }


整个代码比较简单,主要步骤就是:1、拼写类的字符串  2、调用CSharpCodeProvider类进行编译得到程序集(assembly)

接下来就可以利用之前反射的方法来动态调用这个类中的属性了:
 Type type = CreateDynamicType("ConsoleApp.DynamicClass");
            object Class1 = Activator.CreateInstance(type);
            ReflectionSetProperty(Class1, "Prop1", "10");
            object aaa = ReflectionGetProperty(Class1, "Prop1");
            Console.WriteLine(aaa);
            object Class2 = Activator.CreateInstance(type);
            ReflectionSetProperty(Class1, "Prop2", 20);
            object bbb = ReflectionGetProperty(Class1, "Prop2");
            Console.WriteLine(bbb);
有关CompilerParameters的介绍跟多参见
http://technet.microsoft.com/zh-cn/library/system.codedom.compiler.compilerparameters%28v=vs.90%29

你可能感兴趣的:(String,object,C#,assembly,null,Class)