在C#中动态创建一个类

时间:2013-06-14 13:39:13

标签: c# reflection

我可以在runetime创建一个动态类,而不事先知道该类的字段名吗?

例如,如果我让用户进入字符串列表,并且当他发送列表时,我创建一个类,其字段名称为字符串列表。

例如,如果我得到:

List<string> TempList = new List<string>() { "Name1", "Name2" };

我可以像这样在runetime创建一个类吗?

public class CustomClass(){
    public string Name1;
    public string Name2;
}

2 个答案:

答案 0 :(得分:0)

为此,您应该使用:

  

DynamicObject类

有一个链接如何使用它:DynamicObject Class

答案 1 :(得分:0)

如果这是你想要的,你可以使用Reflection.Emit在运行时创建一个类。一种可能的方法是让您执行以下操作。

您可以使用此类来执行整个过程。使用您希望的属性类型关闭类型T.在您的情况下,您将使用类型字符串。

class ClassFromList<T>
{
    public object Instance { get; set; }

    public ClassFromList(List<string> list)
    {
        var type = new DynamicClass().Builder;

        list.ForEach(item => new DynamicProperty<T>(type, item));

        Instance = Activator.CreateInstance(type.CreateType());
    }
}

在上面提到的类中,这个类将为您提供TypeBuilder类型的属性,因此您可以在运行时创建一个类。

class DynamicClass
{
    public TypeBuilder Builder { get; set; }

    public DynamicClass()
    { 
        var name = new AssemblyName("DynamicAssembly");
        var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run);
        var module = assembly.DefineDynamicModule("DynamicModule");

        Builder = module.DefineType("DynamicClass", TypeAttributes.Public);
    }
}

另一方面,下面的课程将创建您希望课程为您实现的属性。

class DynamicProperty<T>
{
    public DynamicProperty(TypeBuilder builder, string name)
    {
        var field = builder.DefineField("_" + name, typeof(T), FieldAttributes.Private);
        var property = builder.DefineProperty(name, PropertyAttributes.None, typeof(T), new Type[0]);
        var getter = builder.DefineMethod("get_" + name, MethodAttributes.Public | MethodAttributes.SpecialName, typeof(T), new Type[0]);
        var setter = builder.DefineMethod("set_" + name, MethodAttributes.Public | MethodAttributes.SpecialName, null, new Type[] { typeof(T) });

        var getGenerator = getter.GetILGenerator();
        var setGenerator = setter.GetILGenerator();

        getGenerator.Emit(OpCodes.Ldarg_0);
        getGenerator.Emit(OpCodes.Ldfld, field);
        getGenerator.Emit(OpCodes.Ret);

        setGenerator.Emit(OpCodes.Ldarg_0);
        setGenerator.Emit(OpCodes.Ldarg_1);
        setGenerator.Emit(OpCodes.Stfld, field);
        setGenerator.Emit(OpCodes.Ret);

        property.SetGetMethod(getter);
        property.SetSetMethod(setter);
    }
}

现在您只需要测试整个过程。下面的代码将创建3个名为“a”,“b”,“c”的字符串类型的属性,分别为它们添加值“value1”,“value2”,“value3”,创建新类的实例,并显示所有属性,它们的类型和价值给你。

class Program
{
    static void Main()
    {
        var list = new List<string>() { "a", "b", "c" };

        var instance = new ClassFromList<string>(list).Instance;

        instance.GetType().GetProperty("a").SetValue(instance, "value1", null);
        instance.GetType().GetProperty("b").SetValue(instance, "value2", null);
        instance.GetType().GetProperty("c").SetValue(instance, "value3", null);

        instance.GetType()
                .GetProperties()
                .ToList()
                .ForEach(x => Console.WriteLine(x.Name + " " + x.PropertyType + " " + x.GetValue(instance, null)));

        Console.Read();
    }
}

编辑:如果你真的需要你班级中的字段,正如我刚才注意到的那样,你应该使用DynamicField类而不是DynamicProperty类,如下所示。但请注意,对于对象之间的数据传输,属性优先于字段。

class DynamicField<T>
{
    public DynamicField(TypeBuilder builder, string name)
    {
        var field = builder.DefineField(name, typeof(T), FieldAttributes.Public);
    }
}