Как я могу создать виртуальные свойства с AssemblyBuilder в C # 4.0? - PullRequest
2 голосов
/ 15 февраля 2010

В настоящее время я работаю над созданием сборки с виртуальными свойствами. Примеры на MSDN создают только нормальные свойства. Как создать класс внутри сборки, которая имеет виртуальные свойства?

Я бы хотел создать класс, подобный этому:

    public class ClassA
    {
        public virtual int Id { get; set; }
        public virtual string Name { get; set; }
        public virtual string ClassName { get; set; }
        public virtual ClassB Partner { get; set; }
    }

    public class ClassB
    {
        public virtual int Id { get; set; }
        public virtual string Name { get; set; }
    }

Класс PropertyBuilder не имеет PropertyAttributes.Virtual, поэтому я не знаю, как создать виртуальное свойство. Если я сам создаю этот класс в Visual Studio, а затем открываю его в Reflector , сами свойства являются виртуальными, поэтому это возможно.

Как это можно сделать?

1 Ответ

4 голосов
/ 15 февраля 2010

Вот пример создания класса во время выполнения, который содержит одно целочисленное свойство Id, которое является виртуальным:

class Program
{
    static void Main(string[] args)
    {
        var aName = new AssemblyName("DynamicAssemblyExample");
        var ab = AppDomain.CurrentDomain.DefineDynamicAssembly(aName, AssemblyBuilderAccess.Run);
        var mb = ab.DefineDynamicModule(aName.Name);
        var tb = mb.DefineType("MyDynamicType", TypeAttributes.Public);
        var fbId = tb.DefineField("_id", typeof(int), FieldAttributes.Private);
        var pbId = tb.DefineProperty("Id", PropertyAttributes.HasDefault, typeof(int), null);

        var getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Virtual;

        var mbIdGetAccessor = tb.DefineMethod("get_Id", getSetAttr, typeof(int), Type.EmptyTypes);

        var numberGetIL = mbIdGetAccessor.GetILGenerator();
        numberGetIL.Emit(OpCodes.Ldarg_0);
        numberGetIL.Emit(OpCodes.Ldfld, fbId);
        numberGetIL.Emit(OpCodes.Ret);

        var mbIdSetAccessor = tb.DefineMethod("set_Id", getSetAttr, null, new Type[] { typeof(int) });

        var numberSetIL = mbIdSetAccessor.GetILGenerator();
        numberSetIL.Emit(OpCodes.Ldarg_0);
        numberSetIL.Emit(OpCodes.Ldarg_1);
        numberSetIL.Emit(OpCodes.Stfld, fbId);
        numberSetIL.Emit(OpCodes.Ret);

        pbId.SetGetMethod(mbIdGetAccessor);
        pbId.SetSetMethod(mbIdSetAccessor);

        var t = tb.CreateType();
        var instance = Activator.CreateInstance(t);
        Console.WriteLine(t.GetProperty("Id").GetGetMethod().IsVirtual);
    }
}

Причина, по которой вы не найдете ничего, связанного с virtual в PropertyBuilder, заключается в том, что свойства не имеют этой концепции. Методы могут быть виртуальными, поэтому, когда вы объявляете виртуальное свойство 1008 *, вы объявляете виртуальные методы получения и установки. Взгляните на перечисление MethodAttributes .

...