System.Reflection.Emit:将类和接口绑定在一起

A我想将一个类和一个接口绑定在一起B,并创建一个实现该接口C的类型。还:CB

  • typeC有一个构造函数,它接受 type 的对象A作为构造函数,我们称之为i

  • A给定从到的所有属性的映射B(假设映射中的所有属性具有相同的类型),则它使用来自 的属性值i

例如:

class A { public string Name { get; set; } } 


interface B { string Name { get; set; } } 


class C : B {

    private readonly A _i;


    public C(A i) { 

        _i = i;

    }


    public string Name

    {

        get => _i.Name;

        set => _i.Name = value;

    }

这就是我所做的(我的意思是“常见” B,我的意思是“来源” A):


/// <summary>

/// Creates a new type dynamically

/// </summary>

public class CustomTypeGenerator<TSource, TCommon>

{

    private readonly TypeBuilder _tb;


    private readonly FieldBuilder _entityFieldBldr;


    private readonly Type _srcType;


    /// <summary>

    /// Initialize custom type builder

    /// </summary>

    public CustomTypeGenerator(IEnumerable<(string CommonPrpName, Type Type, string SourcePrpName)> members)

    {

        var cmType = typeof(TCommon);

        _srcType = typeof(TSource);


        if (!cmType.IsInterface)

        {

            throw new Exception("Type has to be an interface");

        }


        const string assemblyName = "DynamicAseembly123";

        const string typeSignature = "DynamicType123";


        var assemblyBuilder =

            AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(assemblyName), AssemblyBuilderAccess.Run);

        var moduleBuilder = assemblyBuilder.DefineDynamicModule("Module123");


        foreach (var (commonPrpName, type, sourcePrpName) in members)

        {

            EmitProperty(commonPrpName, type, sourcePrpName);

        }


        EmittedType = _tb.CreateType();

    }


}

我得到的异常:


程序集“DynamicAseeembly123,Version=0.0.0.0,Culture=neutral,PublicKeyToken=null”的类型“DynamicType123”中的方法“get_Name”没有实现。


感谢您的任何帮助或提示。


波斯汪
浏览 115回答 1
1回答

素胚勾勒不出你

最初的问题是因为 getter/setter 方法需要MethodAttributes.Virtual能够隐式实现相应的接口方法。添加该标志足以实现所需的隐式接口实现。实际上,您也可以使用DefineMethodOverride隐式实现 - 它不会造成伤害,但不是必需的。上述内容已在您更新的代码中修复。但现在它生成了InvalidProgramException. 这是由于(我猜是复制/粘贴)在set方法主体生成中使用get IL 生成器变量引起的:setIl.MarkLabel(modifyPropertyLbl);setIl.Emit(OpCodes.Ldarg_0);getIl.Emit(OpCodes.Ldfld, _entityFieldBldr); // <--setIl.Emit(OpCodes.Ldarg_1);getIl.Emit(OpCodes.Callvirt, setterMethodInfo); // <--setIl.Emit(OpCodes.Nop);setIl.MarkLabel(exitSetLbl);setIl.Emit(OpCodes.Ret);这当然会为 getter 和 setter 发出无效代码。使用正确的变量,一切都会好起来的。基本上var setIl = setPropMthdBldr.GetILGenerator();setIl.Emit(OpCodes.Ldarg_0);setIl.Emit(OpCodes.Ldfld, _entityFieldBldr);setIl.Emit(OpCodes.Ldarg_1);setIl.Emit(OpCodes.Callvirt, setterMethodInfo);setIl.Emit(OpCodes.Ret);
打开App,查看更多内容
随时随地看视频慕课网APP