c# 写的一个类帮助器(动态生成类 动态类 动态属性)

转载 2011年01月20日 11:07:00

写的一个类帮助器,思路是,可以使用这个帮助器对类动态地控制(在运行时),如添加,删除其成员。

最近要用到这个,在网上找了点资料,也不全面,就自己查msdn帮助文件。自己写了一个,功能还不是很完善,如果大家有兴趣扩展下功能的话,就再好不过了。现在只能控制属性,还不能控制其它成员,如事件,方法等等。

演示一:动态生成类。
演示二:动态添加属性到类。
演示三:动态从类里删除属性。
演示四:动态获取和设置属性值。

类帮助器代码:


// --------------------------------------------------------
// 作者:李剑 msn:newshadowk@hotmail.com qq:50248291
// --------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection.Emit;
using System.Reflection;
using System.Threading;

/// <summary>
/// 类帮助器,可以动态对类,类成员进行控制(添加,删除),目前只支持属性控制。
/// 注意,属性以外的其它成员会被清空,功能还有待完善,使其不影响其它成员。
/// </summary>

public class ClassHelper
{
    
#region 公有方法
    
/// <summary>
    
/// 根据类的类型型创建类实例。
    
/// </summary>
    
/// <param name="t">将要创建的类型。</param>
    
/// <returns>返回创建的类实例。</returns>

    public static object CreateInstance(Type t)
    
{
        
return Activator.CreateInstance(t);
    }


    
/// <summary>
    
/// 根据类的名称,属性列表创建型实例。
    
/// </summary>
    
/// <param name="className">将要创建的类的名称。</param>
    
/// <param name="lcpi">将要创建的类的属性列表。</param>
    
/// <returns>返回创建的类实例</returns>

    public static object CreateInstance(string className, List<CustPropertyInfo> lcpi)
    
{
        Type t 
= BuildType(className);
        t 
= AddProperty(t, lcpi);
        
return Activator.CreateInstance(t);
    }


    
/// <summary>
    
/// 根据属性列表创建类的实例,默认类名为DefaultClass,由于生成的类不是强类型,所以类名可以忽略。
    
/// </summary>
    
/// <param name="lcpi">将要创建的类的属性列表</param>
    
/// <returns>返回创建的类的实例。</returns>

    public static object CreateInstance(List<CustPropertyInfo> lcpi)
    
{
        
return CreateInstance("DefaultClass", lcpi);
    }


    
/// <summary>
    
/// 根据类的实例设置类的属性。
    
/// </summary>
    
/// <param name="classInstance">将要设置的类的实例。</param>
    
/// <param name="propertyName">将要设置属性名。</param>
    
/// <param name="propertSetValue">将要设置属性值。</param>

    public static void SetPropertyValue(object classInstance, string propertyName, object propertSetValue)
    
{
        classInstance.GetType().InvokeMember(propertyName, BindingFlags.SetProperty,
                                      
null, classInstance, new object[] { Convert.ChangeType(propertSetValue, propertSetValue.GetType()) });
    }


    
/// <summary>
    
/// 根据类的实例获取类的属性。
    
/// </summary>
    
/// <param name="classInstance">将要获取的类的实例</param>
    
/// <param name="propertyName">将要设置的属性名。</param>
    
/// <returns>返回获取的类的属性。</returns>

    public static object GetPropertyValue(object classInstance, string propertyName)
    
{
        
return classInstance.GetType().InvokeMember(propertyName, BindingFlags.GetProperty,
                                                      
null, classInstance, new object[] { });
    }


    
/// <summary>
    
/// 创建一个没有成员的类型的实例,类名为"DefaultClass"。
    
/// </summary>
    
/// <returns>返回创建的类型的实例。</returns>

    public static Type BuildType()
    
{
        
return BuildType("DefaultClass");
    }


    
/// <summary>
    
/// 根据类名创建一个没有成员的类型的实例。
    
/// </summary>
    
/// <param name="className">将要创建的类型的实例的类名。</param>
    
/// <returns>返回创建的类型的实例。</returns>

    public static Type BuildType(string className)
    
{

        AppDomain myDomain 
= Thread.GetDomain();
        AssemblyName myAsmName 
= new AssemblyName();
        myAsmName.Name 
= "MyDynamicAssembly";

        
//创建一个永久程序集,设置为AssemblyBuilderAccess.RunAndSave。
        AssemblyBuilder myAsmBuilder = myDomain.DefineDynamicAssembly(myAsmName,
                                                        AssemblyBuilderAccess.RunAndSave);

        
//创建一个永久单模程序块。
        ModuleBuilder myModBuilder =
            myAsmBuilder.DefineDynamicModule(myAsmName.Name, myAsmName.Name 
+ ".dll");
        
//创建TypeBuilder。
        TypeBuilder myTypeBuilder = myModBuilder.DefineType(className,
                                                        TypeAttributes.Public);

        
//创建类型。
        Type retval = myTypeBuilder.CreateType();

        
//保存程序集,以便可以被Ildasm.exe解析,或被测试程序引用。
        myAsmBuilder.Save(myAsmName.Name + ".dll");
        
return retval;
    }


    
/// <summary>
    
/// 添加属性到类型的实例,注意:该操作会将其它成员清除掉,其功能有待完善。
    
/// </summary>
    
/// <param name="classType">指定类型的实例。</param>
    
/// <param name="lcpi">表示属性的一个列表。</param>
    
/// <returns>返回处理过的类型的实例。</returns>

    public static Type AddProperty(Type classType, List<CustPropertyInfo> lcpi)
    
{
        
//合并先前的属性,以便一起在下一步进行处理。
        MergeProperty(classType, lcpi);
        
//把属性加入到Type。
        return AddPropertyToType(classType, lcpi);
    }


    
/// <summary>
    
/// 添加属性到类型的实例,注意:该操作会将其它成员清除掉,其功能有待完善。
    
/// </summary>
    
/// <param name="classType">指定类型的实例。</param>
    
/// <param name="cpi">表示一个属性。</param>
    
/// <returns>返回处理过的类型的实例。</returns>

    public static Type AddProperty(Type classType, CustPropertyInfo cpi)
    
{
        List
<CustPropertyInfo> lcpi = new List<CustPropertyInfo>();
        lcpi.Add(cpi);
        
//合并先前的属性,以便一起在下一步进行处理。
        MergeProperty(classType, lcpi);
        
//把属性加入到Type。
        return AddPropertyToType(classType, lcpi);
    }


    
/// <summary>
    
/// 从类型的实例中移除属性,注意:该操作会将其它成员清除掉,其功能有待完善。
    
/// </summary>
    
/// <param name="classType">指定类型的实例。</param>
    
/// <param name="cpi">要移除的属性。</param>
    
/// <returns>返回处理过的类型的实例。</returns>

    public static Type DeleteProperty(Type classType, string propertyName)
    
{
        List
<string> ls = new List<string>();
        ls.Add(propertyName);

        
//合并先前的属性,以便一起在下一步进行处理。
        List<CustPropertyInfo> lcpi = SeparateProperty(classType, ls);
        
//把属性加入到Type。
        return AddPropertyToType(classType, lcpi);
    }


    
/// <summary>
    
/// 从类型的实例中移除属性,注意:该操作会将其它成员清除掉,其功能有待完善。
    
/// </summary>
    
/// <param name="classType">指定类型的实例。</param>
    
/// <param name="lcpi">要移除的属性列表。</param>
    
/// <returns>返回处理过的类型的实例。</returns>

    public static Type DeleteProperty(Type classType, List<string> ls)
    
{
        
//合并先前的属性,以便一起在下一步进行处理。
        List<CustPropertyInfo> lcpi = SeparateProperty(classType, ls);
        
//把属性加入到Type。
        return AddPropertyToType(classType, lcpi);
    }

    
#endregion


    
#region 私有方法
    
/// <summary>
    
/// 把类型的实例t和lcpi参数里的属性进行合并。
    
/// </summary>
    
/// <param name="t">实例t</param>
    
/// <param name="lcpi">里面包含属性列表的信息。</param>

    private static void MergeProperty(Type t, List<CustPropertyInfo> lcpi)
    
{
        CustPropertyInfo cpi;
        
foreach (PropertyInfo pi in t.GetProperties())
        
{
            cpi 
= new CustPropertyInfo(pi.PropertyType.FullName, pi.Name);
            lcpi.Add(cpi);
        }

    }


    
/// <summary>
    
/// 从类型的实例t的属性移除属性列表lcpi,返回的新属性列表在lcpi中。
    
/// </summary>
    
/// <param name="t">类型的实例t。</param>
    
/// <param name="lcpi">要移除的属性列表。</param>

    private static List<CustPropertyInfo> SeparateProperty(Type t, List<string> ls)
    
{
        List
<CustPropertyInfo> ret = new List<CustPropertyInfo>();
        CustPropertyInfo cpi;
        
foreach (PropertyInfo pi in t.GetProperties())
        
{
            
foreach (string s in ls)
            
{
                
if (pi.Name != s)
                
{
                    cpi 
= new CustPropertyInfo(pi.PropertyType.FullName, pi.Name);
                    ret.Add(cpi);
                }

            }

        }


        
return ret;
    }


    
/// <summary>
    
/// 把lcpi参数里的属性加入到myTypeBuilder中。注意:该操作会将其它成员清除掉,其功能有待完善。
    
/// </summary>
    
/// <param name="myTypeBuilder">类型构造器的实例。</param>
    
/// <param name="lcpi">里面包含属性列表的信息。</param>

    private static void AddPropertyToTypeBuilder(TypeBuilder myTypeBuilder, List<CustPropertyInfo> lcpi)
    
{
        FieldBuilder customerNameBldr;
        PropertyBuilder custNamePropBldr;
        MethodBuilder custNameGetPropMthdBldr;
        MethodBuilder custNameSetPropMthdBldr;
        MethodAttributes getSetAttr;
        ILGenerator custNameGetIL;
        ILGenerator custNameSetIL;

        
// 属性Set和Get方法要一个专门的属性。这里设置为Public。
        getSetAttr =
            MethodAttributes.Public 
| MethodAttributes.SpecialName |
                MethodAttributes.HideBySig;

        
// 添加属性到myTypeBuilder。
        foreach (CustPropertyInfo cpi in lcpi)
        
{
            
//定义字段。
            customerNameBldr = myTypeBuilder.DefineField(cpi.FieldName,
                                                             Type.GetType(cpi.Type),
                                                             FieldAttributes.Private);

            
//定义属性。
            
//最后一个参数为null,因为属性没有参数。
            custNamePropBldr = myTypeBuilder.DefineProperty(cpi.PropertyName,
                                                             PropertyAttributes.HasDefault,
                                                             Type.GetType(cpi.Type),
                                                             
null);


            
//定义Get方法。
            custNameGetPropMthdBldr =
                myTypeBuilder.DefineMethod(cpi.GetPropertyMethodName,
                                           getSetAttr,
                                           Type.GetType(cpi.Type),
                                           Type.EmptyTypes);

            custNameGetIL 
= custNameGetPropMthdBldr.GetILGenerator();

            custNameGetIL.Emit(OpCodes.Ldarg_0);
            custNameGetIL.Emit(OpCodes.Ldfld, customerNameBldr);
            custNameGetIL.Emit(OpCodes.Ret);

            
//定义Set方法。
            custNameSetPropMthdBldr =
                myTypeBuilder.DefineMethod(cpi.SetPropertyMethodName,
                                           getSetAttr,
                                           
null,
                                           
new Type[] { Type.GetType(cpi.Type) });

            custNameSetIL 
= custNameSetPropMthdBldr.GetILGenerator();

            custNameSetIL.Emit(OpCodes.Ldarg_0);
            custNameSetIL.Emit(OpCodes.Ldarg_1);
            custNameSetIL.Emit(OpCodes.Stfld, customerNameBldr);
            custNameSetIL.Emit(OpCodes.Ret);

            
//把创建的两个方法(Get,Set)加入到PropertyBuilder中。
            custNamePropBldr.SetGetMethod(custNameGetPropMthdBldr);
            custNamePropBldr.SetSetMethod(custNameSetPropMthdBldr);
        }

    }


    
/// <summary>
    
/// 把属性加入到类型的实例。
    
/// </summary>
    
/// <param name="classType">类型的实例。</param>
    
/// <param name="lcpi">要加入的属性列表。</param>
    
/// <returns>返回处理过的类型的实例。</returns>

    public static Type AddPropertyToType(Type classType, List<CustPropertyInfo> lcpi)
    
{
        AppDomain myDomain 
= Thread.GetDomain();
        AssemblyName myAsmName 
= new AssemblyName();
        myAsmName.Name 
= "MyDynamicAssembly";

        
//创建一个永久程序集,设置为AssemblyBuilderAccess.RunAndSave。
        AssemblyBuilder myAsmBuilder = myDomain.DefineDynamicAssembly(myAsmName,
                                                        AssemblyBuilderAccess.RunAndSave);

        
//创建一个永久单模程序块。
        ModuleBuilder myModBuilder =
            myAsmBuilder.DefineDynamicModule(myAsmName.Name, myAsmName.Name 
+ ".dll");
        
//创建TypeBuilder。
        TypeBuilder myTypeBuilder = myModBuilder.DefineType(classType.FullName,
                                                        TypeAttributes.Public);

        
//把lcpi中定义的属性加入到TypeBuilder。将清空其它的成员。其功能有待扩展,使其不影响其它成员。
        AddPropertyToTypeBuilder(myTypeBuilder, lcpi);

        
//创建类型。
        Type retval = myTypeBuilder.CreateType();

        
//保存程序集,以便可以被Ildasm.exe解析,或被测试程序引用。
        myAsmBuilder.Save(myAsmName.Name + ".dll");
        
return retval;
    }

    
#endregion


    
#region 辅助类
    
/// <summary>
    
/// 自定义的属性信息类型。
    
/// </summary>

    public class CustPropertyInfo
    
{
        
private string propertyName;
        
private string type;

        
/// <summary>
        
/// 空构造。
        
/// </summary>

        public CustPropertyInfo() { }

        
/// <summary>
        
/// 根据属性类型名称,属性名称构造实例。
        
/// </summary>
        
/// <param name="type">属性类型名称。</param>
        
/// <param name="propertyName">属性名称。</param>

        public CustPropertyInfo(string type, string propertyName)
        
{
            
this.type = type;
            
this.propertyName = propertyName;
        }


        
/// <summary>
        
/// 获取或设置属性类型名称。
        
/// </summary>

        public string Type
        
{
            
get return type; }
            
set { type = value; }
        }


        
/// <summary>
        
/// 获取或设置属性名称。
        
/// </summary>

        public string PropertyName
        
{
            
get return propertyName; }
            
set { propertyName = value; }
        }


        
/// <summary>
        
/// 获取属性字段名称。
        
/// </summary>

        public string FieldName
        
{
            
get return propertyName.Substring(01).ToLower() + propertyName.Substring(1); }
        }


        
/// <summary>
        
/// 获取属性在IL中的Set方法名。
        
/// </summary>

        public string SetPropertyMethodName
        
{
            
get return "set_" + PropertyName; }
        }


        
/// <summary>
        
///  获取属性在IL中的Get方法名。
        
/// </summary>

        public string GetPropertyMethodName
        
{
            
get return "get_" + PropertyName; }
        }

    }

    
#endregion

}


 显示程序代码:


// --------------------------------------------------------
// 作者:李剑 msn:newshadowk@hotmail.com qq:50248291
// --------------------------------------------------------
using System;
using System.Threading;
using System.Reflection;
using System.Collections.Generic;

class ClassHelperDemo
{
    
public static void Main()
    
{
        
#region 演示一:动态生成类。
        
//生成一个类t。
        Type t = ClassHelper.BuildType("MyClass");
        
#endregion


        
#region 演示二:动态添加属性到类。
        
//先定义两个属性。
        List<ClassHelper.CustPropertyInfo> lcpi = new List<ClassHelper.CustPropertyInfo>();
        ClassHelper.CustPropertyInfo cpi;

        cpi 
= new ClassHelper.CustPropertyInfo("System.String""S1");
        lcpi.Add(cpi);
        cpi 
= new ClassHelper.CustPropertyInfo("System.String""S2");
        lcpi.Add(cpi);



        
//再加入上面定义的两个属性到我们生成的类t。
        t = ClassHelper.AddProperty(t, lcpi);

        
//把它显示出来。
        DispProperty(t);

        
//再定义两个属性。
        lcpi.Clear();
        cpi 
= new ClassHelper.CustPropertyInfo("System.Int32""I1");
        lcpi.Add(cpi);
        cpi 
= new ClassHelper.CustPropertyInfo("System.Int32""I2");
        lcpi.Add(cpi);

        
//再加入上面定义的两个属性到我们生成的类t。
        t = ClassHelper.AddProperty(t, lcpi);

        
//再把它显示出来,看看有没有增加到4个属性。
        DispProperty(t);
        
#endregion


        
#region 演示三:动态从类里删除属性。
        
//把'S1'属性从类t中删除。
        t = ClassHelper.DeleteProperty(t, "S1");
        
//显示出来,可以看到'S1'不见了。
        DispProperty(t);

        
#endregion

        
        
#region 演示四:动态获取和设置属性值。
        
//先生成一个类t的实例o。
        object o = ClassHelper.CreateInstance(t);

        
//给S2,I2属性赋值。
        ClassHelper.SetPropertyValue(o, "S2""abcd");
        ClassHelper.SetPropertyValue(o, 
"I2"1234);

        
//再把S2,I2的属性值显示出来。
        Console.WriteLine("S2 = {0}", ClassHelper.GetPropertyValue(o, "S2"));
        Console.WriteLine(
"I2 = {0}", ClassHelper.GetPropertyValue(o, "I2"));
        
#endregion


        Console.Read();
    }


    
public static void DispProperty(Type t)
    
{
        Console.WriteLine(
"ClassName '{0}'", t.Name);
        
foreach (PropertyInfo pInfo in t.GetProperties())
        
{
            Console.WriteLine(
"Has Property '{0}'", pInfo.ToString());
        }

        Console.WriteLine(
"");
    }

}


输出:

ClassName 'MyClass'
Has Property 'System.String S1'
Has Property 'System.String S2'

ClassName 'MyClass'
Has Property 'Int32 I1'
Has Property 'Int32 I2'
Has Property 'System.String S1'
Has Property 'System.String S2'

ClassName 'MyClass'
Has Property 'Int32 I1'
Has Property 'Int32 I2'
Has Property 'System.String S2'

S2 = abcd
I2 = 1234

Java动态生成类以及动态添加属性

有个技术实现需求:动态生成类,其中类中的属性来自参数对象中的全部属性以及来自参数对象propertities文件。   那么技术实现支持:使用cgilib代理。   具体的实现步骤:   1.c...
  • llhhyy1989
  • llhhyy1989
  • 2014年08月10日 17:25
  • 14693

C# 类动态添加属性、方法

问题:   需要动态为WPF中的DataGrid添加列,并动态绑定相应数据.(此处仅实现动态属性的添加和使用,关于动态方法的添加和使用详见推荐阅读) 实现关键点:   目标类继承DynamicO...
  • guokeeryi_
  • guokeeryi_
  • 2015年03月16日 23:00
  • 1712

c# 写的一个类帮助器(动态生成类 动态类 动态属性)

写的一个类帮助器,思路是,可以使用这个帮助器对类动态地控制(在运行时),如添加,删除其成员。最近要用到这个,在网上找了点资料,也不全面,就自己查msdn帮助文件。自己写了一个,功能还不是很完善,如果大...
  • lanmao100
  • lanmao100
  • 2008年01月23日 17:57
  • 3742

类帮助器(动态生成类 动态类 动态属性)

出处:http://blog.u.ulolo.com/Journal/tianxiawenzhangyiyangchao/6480 写的一个类帮助器,思路是,可以使用这个帮助器对类动态地控制(在...
  • UR_Not_Alone
  • UR_Not_Alone
  • 2012年08月03日 13:47
  • 456

C#类动态添加属性

动态类实现 using System; using System.Collections.Generic; using System.Reflection.Emit; using Sys...
  • ajianchina
  • ajianchina
  • 2015年09月16日 14:59
  • 6479

C# 动态创建一个类

C# 在运行时动态的创建类型是通过动态生成C#源代码,然后通过编译器编译成程序集的方式实现动态创建类型的。 主要功能代码如下: public static Assembly NewAs...
  • w4477111
  • w4477111
  • 2017年07月09日 23:54
  • 303

C#动态创建和动态使用程序集、类、方法、字段等

C#动态创建和动态使用程序集、类、方法、字段等 分类: 技术交流 2011-08-15 16:08 1341人阅读 评论(3) 收藏 举报 c#microsoftstringobjectnu...
  • minsenwu
  • minsenwu
  • 2015年03月19日 15:20
  • 2058

Java动态创建类

Java可以创建动态类,学习看到,此处作为笔记。 代码如下: import java.io.IOException; import java.lang.reflect.Method; import...
  • liang_henry
  • liang_henry
  • 2016年01月04日 17:12
  • 1685

Java 动态生成类和实例, 并注入方法

Java官方支持的, 必须要有接口才行 import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHa...
  • David_Ding
  • David_Ding
  • 2016年12月29日 16:29
  • 4320

C#中利用反射,动态生成类的实例

在java语言中,运用Class.Class.forName(),可以根据一个类的类名(Type?),动态生成这个类的一个实例,在C#中该如何进行这样的操作呢?方法如下:System.Activato...
  • vvfish119
  • vvfish119
  • 2005年11月18日 13:23
  • 4592
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:c# 写的一个类帮助器(动态生成类 动态类 动态属性)
举报原因:
原因补充:

(最多只允许输入30个字)