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

这篇具有很好参考价值的文章主要介绍了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");

        }

总结

动态类可能在开发应用中使用的不多,但是对于一些特殊开发需求还是比较有用的。如果此代码能对别人起到帮助作用,我自然也是感到相当欣慰的。文章来源地址https://www.toymoban.com/news/detail-514006.html

到了这里,关于C# 动态类创建、动态创建属性和取动态类属性值的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C# 文件操作(复制、移动、重命名、创建、打开、删除)

    目录 一、简介 二、创建文件 三、写入文件 四、读取文件 五、复制文件 六、移动文件 七、重命名文件 八、删除文件 结束 C#中的IO(Input/Output)操作包括读取和写入文件、读取和写入流、以及操作目录和文件夹等。这些操作都可以通过System.IO命名空间中的类实现。下面对C

    2024年02月01日
    浏览(47)
  • 【创建型设计模式】C#设计模式之工厂模式,以及通过反射实现动态工厂。

    题目如下: 简单工厂实现: 上述代码给出了抽象基类的基本定义,和泛型工厂的实现方式,以及调用方式。 值得注意的是 where T : Car, new() 这个条件: where T : Car, new() 是对泛型类型参数 T 的约束。这个约束表明泛型类型参数 T 必须满足两个条件: T 必须是 Car 类或者其派生类

    2024年02月11日
    浏览(40)
  • C#匿名类型

    匿名类型提供了一种方便的方法,可用来将一组只读属性封装到单个对象中,而无需首先显式定义一个类型。 类型名由编译器生成,并且不能在源代码级使用。 每个属性的类型由编译器推断。 可结合使用  new  运算符和对象初始值设定项创建匿名类型。  

    2024年02月11日
    浏览(31)
  • 《Linux操作系统编程》 第十章 线程与线程控制: 线程的创建、终止和取消,detach以及线程属性

    🌷🍁 博主 libin9iOak带您 Go to New World.✨🍁 🦄 个人主页——libin9iOak的博客🎐 🐳 《面试题大全》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 🌊 《IDEA开发秘籍》学会IDEA常用操作,工作效率翻倍~💐 🪁🍁 希望本文能够给您带来一定的帮助🌸文章粗浅,敬

    2024年02月11日
    浏览(89)
  • C#匿名方法增加、删除委托

    匿名方法给我们带来了方便,那么如何增加删除匿名方法中附加的委托(事件)呢 一般写法: 1 2 3 4 this .Loaded += (sender, e) =       {              //Do something       }; 进化写法: 1 2 3 4 5 6 7 this .Loaded += new   RoutedEventHandler(FormulaAssign_Loaded); void   FormulaAssign_Loaded( objec

    2024年02月11日
    浏览(34)
  • C# 匿名类型之 RuntimeBinderException

    匿名类型在某些场景下使用起来还是比较方便,比如某个类型只会使用一次,那这个时候定义一个 Class 就没有多少意义,完全可以使用匿名类型来解决,但是在跨项目使用时,还是需要注意避免出现 RuntimeBinderException 问题 比如我们有一个 netstandard2.0 类型的类库项目,里面有

    2023年04月13日
    浏览(29)
  • C#学习,委托,事件,泛型,匿名方法

    目录 委托 声明委托 实例化委托 委托的多播 委托的用途 事件 通过事件使用委托 声明事件 泛型 泛型的特性 泛型方法 泛型的委托 匿名方法 编写匿名方法的语法 类似于指针,委托是存有对某个方法的引用的一种引用类型变量,引用可以在运行时被改变。特别用于实现事件和

    2024年02月12日
    浏览(44)
  • C# Func和匿名方法 简单使用

    .NET Framework 3.5 引入了变体支持,用于在 C# 中匹配所有委托的方法签名和委托类型。 这表明不仅可以将具有匹配签名的方法分配给委托,还可以将返回派生程度较大的派生类型的方法分配给委托(协变),或者如果方法所接受参数的派生类型所具有的派生程度小于委托类型指

    2024年02月15日
    浏览(44)
  • C#中错误:线程间操作无效,从不是创建控件的线程访问它。

    一、原因分析 跨线程调用控件会出现这个错误的原因是因为:.NET禁止了跨线程调用控件, 否则谁都可以操作控件,最后可能造成错误。 所以不是在创建控件所在的线程内调用就会发生这样的错误。 二、解决办法 方法1:设置CheckForIllegalCrossThreadCalls =false 是能去掉这个检查的

    2024年02月15日
    浏览(37)
  • C# 匿名方法和Lambda表达式

    1.匿名方法的演变 匿名方法是为了简化委托的实现,方便调用委托方法而出现的,同时,匿名方法也是学好lambda表达式的基础。在委托调用的方法中,如果方法只被调用一次,这个时候我们就没有必要创建具名方法,从而用匿名方法更为方便。 下面一段代码是声明并使用了一

    2024年02月15日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包