jeudi 28 novembre 2019

Implementing an interface using Reflection.Emit

I am trying to implement an interface using Reflection.Emit. Code works just fine if I simply try to add a property, but it doesn't work as soon as I try to implement the interface.

static void AddProperties(TypeBuilder typeBuilder, MemberInfo Member)
{
    FieldBuilder backingField = typeBuilder.DefineField(BackingFieldNameByConvention(Member.Name), Member.MemberType(), FieldAttributes.Private);
    PropertyBuilder property = typeBuilder.DefineProperty(Member.Name, PropertyAttributes.HasDefault, Member.MemberType(), null);

    MethodAttributes getterSetterAttributes =  MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;

    MethodBuilder getter = typeBuilder.DefineMethod($"get_{Member.Name}", getterSetterAttributes, Member.MemberType(), Type.EmptyTypes);
    ILGenerator getterIL = getter.GetILGenerator();
    getterIL.Emit(OpCodes.Ldarg_0);
    getterIL.Emit(OpCodes.Ldfld, backingField);
    getterIL.Emit(OpCodes.Ret);

    MethodBuilder setter =  typeBuilder.DefineMethod($"set_{Member.Name}", getterSetterAttributes, null, new Type[] { Member.MemberType() });
    ILGenerator setterIL = setter.GetILGenerator();
    setterIL.Emit(OpCodes.Ldarg_0);
    setterIL.Emit(OpCodes.Ldarg_1);
    setterIL.Emit(OpCodes.Stfld, backingField);
    setterIL.Emit(OpCodes.Ret);

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

static string BackingFieldNameByConvention(string FieldName)
=> $"<{FieldName}>k__BackingField";

which is being called by this function

public static Type BuildType(string TypeName, List<MemberInfo> MemberInfoList, Type ParentType, List<Type> InheritanceDependencyList)
{
    var typeBuilder = GetTypeBuilder(TypeName, ParentType);
    foreach (var InheritanceDependency in InheritanceDependencyList)
    {
        var members = InheritanceDependency.GetProperties();
        typeBuilder.AddInterfaceImplementation(InheritanceDependency);

        foreach(var member in members)
            AddProperties(typeBuilder, member);
    }


    AddFields(typeBuilder, MemberInfoList);

    return typeBuilder.CreateType();
}

I also moved the inheritance part BuildType method from GetTypeBuilder's moduleBuilder.DefineType() method. I don't think it should affect the code at all.

static TypeBuilder GetTypeBuilder(string TypeName, Type ParentType)
{
    AssemblyName assemblyName = new AssemblyName(Guid.NewGuid().ToString());
    var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndCollect);

    ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
    var typeBuilder = moduleBuilder.DefineType(TypeName, TypeAttributes.Public, ParentType);

    return typeBuilder;
}

Anyway, if I remove typeBuilder.AddInterfaceImplementation(InheritanceDependency);, everything works fine. Properties get implemented perfectly. If I use this line, I get the following error. I don't understand why I still get this error even if the properties get successfully implemented.

"Method 'get_Region' in type 'foobar' from assembly '82783185-8bc6-47d7-b8f3-8a880c257515, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation."




Aucun commentaire:

Enregistrer un commentaire