为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
波斯汪 2023-08-13 13:51:18
A我想将一个类和一个接口绑定在一起B,并创建一个实现该接口C的类型。还:CBtypeC有一个构造函数,它接受 type 的对象A作为构造函数,我们称之为iA给定从到的所有属性的映射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”没有实现。感谢您的任何帮助或提示。
查看完整描述

1 回答

?
素胚勾勒不出你

TA贡献1827条经验 获得超9个赞

最初的问题是因为 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);


查看完整回答
反对 回复 2023-08-13
  • 1 回答
  • 0 关注
  • 108 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信