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

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

最近要用到这个,在网上找了点资料,也不全面,就自己查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


    
辅助类
}


 

 显示程序代码:


// --------------------------------------------------------
// 作者:李剑 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

 
  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值