3

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

Я хотел бы иметь возможность создать класс, как это:

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, свойства будут виртуальными, так что это возможно.

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

ответ

3

Вот пример создания класса во время выполнения, который содержит одно целое свойство 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 это потому, что свойства Дон» У меня есть эта концепция. Методы могут быть виртуальными, поэтому, когда вы объявляете виртуальное свойство , вы объявляете методы виртуального приемника и сеттера. Взгляните на список MethodAttributes.

+0

ab.Save() не сохранить созданную Ассамблею (даже с AssemblyBuilderAccess установлен в RunAndSave) Вы можете попробовать сохранения и загрузки сборки обратно в память? Я использую это в своем собственном программном обеспечении для работы с ошибкой в ​​платформе .NET, которая определяет сборку как сборку времени выполнения даже после ее сохранения. Но если я использую это в своем коде, он не сохраняет никаких свойств или методов. –

+0

Я сделал что-то не так с вашим кодом, который остановил его от работы. После повторной попытки, он отлично работает! –

+0

@ThijsCramer, если вы передадите имя файла методу DefineDynamicModule, файл будет сохранен при дальнейшем использовании имени ab.Save (FileName). Я не знаю, является ли это ошибкой или функцией, потому что вам нужно указать имена файлов в обоих местах, и оба могут быть разными. Сборка dll будет ссылаться на модуль dll –

 Смежные вопросы

  • Нет связанных вопросов^_^