C# 动态类创建、动态创建属性和取动态类属性值


前言

在对匿名类操作时,参考了一篇博主的文章:https://www.cnblogs.com/elves/p/6087186.html,其中动态类的部分是非常有指导意义的,原博文的动态类是创建字符串属性的动态类,现对其进行加工,略做修改,可以适用创建byte,short,unshort,int,long,bool,float,doubel,List属性(T限于以上基础类型)的动态类。同时因本人年龄偏大,记忆力实在比不上年青人,所以也当做记事本以当纪录。


提示:对以下代码的理解,本人也只是知其部分然,而不尽其所以然,各位观者莫怪,能用最好。

一、涉及到的引用

using Microsoft.CSharp;
using System;
using System.Text;
using System.CodeDom.Compiler;
using System.Reflection;

二、代码

#region 生成自定义动态类
    public static class DynamicClassHelper
    {
        /// <summary>
        /// 创建属性
        /// </summary>
        /// <param name="propertyType">属性基础类型(byte/int/string/float/double/bool等)和List基础类型</param>
        /// <param name="propertyName">属性名称</param>
        /// <param name="propertyDefaultValue">属性初始值</param>
        /// <returns></returns>
        private static string PropertyString(string propertyType, string propertyName, string propertyDefaultValue)
        {
            StringBuilder sbproperty = new StringBuilder();
            sbproperty.Append(" private " + propertyType + "  _" + propertyName + "   =  " + propertyDefaultValue + ";\n");
            sbproperty.Append(" public " + propertyType + " " + propertyName + "\n");
            sbproperty.Append(" {\n");
            sbproperty.Append(" get{   return   _" + propertyName + ";}   \n");
            sbproperty.Append(" set{   _" + propertyName + "   =   value;   }\n");
            sbproperty.Append(" }\n");
            return sbproperty.ToString();
        }
        /// <summary>
        /// 创建动态类
        /// </summary>
        /// <param name="className">动态类名字</param>
        /// <param name="propertyList">属性列表</param>
        /// <returns></returns>
        public static Assembly Newassembly(string className, List<string[]> propertyList)
        {
            //创建编译器实例。   
            CSharpCodeProvider provider = new CSharpCodeProvider();
            //设置编译参数。   
            CompilerParameters paras = new CompilerParameters();
            //编译器生成的临时文件,参数2为true,放置为当前文件夹下,false则放入windows的temp文件夹下
            paras.TempFiles = new TempFileCollection(".", false);
            //如果为true,则生成exe文件,false会生成临时dll文件
            paras.GenerateExecutable = false;
            paras.GenerateInMemory = true;

            //创建动态代码。   
            StringBuilder classsource = new StringBuilder();
            //float、bool等类型需要引用System
            classsource.Append("using System;\n");
            //List需要引用System.Collections.Generic
            classsource.Append("using System.Collections.Generic;\n");
            classsource.Append("public class " + className + " \n");
            classsource.Append("{\n");

            try
            {
                //创建属性。   
                for (int i = 0; i < propertyList.Count; i++)
                {
                    classsource.Append(PropertyString(propertyList[i][0], propertyList[i][1], propertyList[i][2]));
                }
                classsource.Append("}");
                System.Diagnostics.Debug.WriteLine(classsource.ToString());
                //编译代码。   
                CompilerResults result = provider.CompileAssemblyFromSource(paras, classsource.ToString());
                //获取编译后的程序集。   
                Assembly assembly = result.CompiledAssembly;

                return assembly;
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
                return null;
            }

        }
        /// <summary>
        /// 给属性赋值
        /// </summary>
        /// <param name="objclass">先进行dynamic objclass = assembly.CreateInstance(className),得到的objclass</param>
        /// <param name="propertyname">属性名称</param>
        /// <param name="value">属性值</param>
        public static void ReflectionSetValue(object objclass, string propertyname, object value)
        {
            PropertyInfo[] infos = objclass.GetType().GetProperties();

            try
            {
                foreach (PropertyInfo info in infos)
                {
                    if (info.Name == propertyname && info.CanWrite)
                    {
                        info.SetValue(objclass, value, null);
                    }
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
            }

        }
        /// <summary>
        /// 得到属性值
        /// </summary>
        /// <param name="objclass">先进行dynamic objclass = assembly.CreateInstance(className),得到的objclass</param>
        /// <param name="propertyname">属性名称</param>
        /// <returns>属性值,是object类型,使用时记得转换</returns>
        public static object ReflectionGetValue(object objclass, string propertyname)
        {
            object result = null;
            PropertyInfo[] infos = objclass.GetType().GetProperties();
            try
            {
                foreach (PropertyInfo info in infos)
                {
                    if (info.Name == propertyname && info.CanRead)
                    {
                        System.Console.WriteLine(info.GetValue(objclass, null));
                        result = info.GetValue(objclass, null);
                    }
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
                result = null;
            }

            return result;
        }

        

    }
    #endregion

三、 使用方法

1、动态类的属性列表初始化,是List<string[]>类型,其中string[]数组有三个字符串组成,第一个是属性的类型,第二个是属性名称,第三个是属性的初始值,这三项都必须填写,否则将无法构建属性列表。对于byte、short、unshort、long可用"0"进行初始化,其他数值要用到相应的强制转换类型符。
2、动态类的属性赋值,首先要记得把得到的动态类程序集实例化,就是 dynamic objclass = assembly.CreateInstance(className)这条语句,然后才能进行属性赋值。具体数值原参数为object类,因此,对byte、short、unshort、float等也要强制转换,以下Demo也说得清楚。

        /// <summary>
        /// 例子
        /// </summary>
        public static void Demo()
        {
            //初始化动态类的属性,并且必须要赋初值,全部用字符串表示,
            List<string[]> Propertys = new List<string[]>
                {
                    new string[]{ "byte","studentNo","0"},//byte类型,初始值0或类似(byte)100
                    new string[]{ "char","level","'A'"},//字符型,用单引号加字符
                    new string[]{"short","workdate", "(short)100" },//short类型,用0或类似(short)100
                    new string[] { "int", "id" ,"0"},
                    new string[] { "string","userName","null"},
                    new string[]{"bool","sex","true" },
                    new string[]{"DateTime","jobTime","DateTime.Now" },
                    new string[]{ "List<float>","scores","new List<float>()"},
                    new string[]{ "double","phonePower","0.0"}
                };

            //创建动态类,构建一个程序集
            string className = "Person";
            Assembly assembly = DynamicClassHelper.Newassembly(className, Propertys);

            //构建动态类的实例
            dynamic objclass = assembly.CreateInstance(className);
            //给动态类属性赋值,byte/short/unshort/long/float要强制转换
            DynamicClassHelper.ReflectionSetValue(objclass, "studentNo", (byte)10);
            DynamicClassHelper.ReflectionSetValue(objclass, "level", 'A');
            DynamicClassHelper.ReflectionSetValue(objclass, "workdate", (short)300);
            DynamicClassHelper.ReflectionSetValue(objclass, "id", 1);
            DynamicClassHelper.ReflectionSetValue(objclass, "userName", "XiaoMing Li");
            DynamicClassHelper.ReflectionSetValue(objclass, "sex", true);
            DynamicClassHelper.ReflectionSetValue(objclass, "jobTime", new DateTime(2015, 8, 1));
            DynamicClassHelper.ReflectionSetValue(objclass, "scores", new List<float> { (float)98.2, (float)95.0, (float)88.8 });
            DynamicClassHelper.ReflectionSetValue(objclass, "phonePower", 0.89);

            //获取动态类相应的属性值,因为返回的是object类,要强制转换后使用(List测试时,可以省略强制转换)
            double phonePower = (double)DynamicClassHelper.ReflectionGetValue(objclass, "phonePower");
            List<float> scores = (List<float>)DynamicClassHelper.ReflectionGetValue(objclass, "scores");

        }

总结

动态类可能在开发应用中使用的不多,但是对于一些特殊开发需求还是比较有用的。如果此代码能对别人起到帮助作用,我自然也是感到相当欣慰的。

  • 16
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值