在运行时使用TypeBuilder创建类,并在属性getter中调用函数

我需要在运行时生成一个可以正常工作的类型。 但是,我还需要在生成的属性获取器中调用现有函数,以修改返回值。 这是生成属性的函数:

        private PropertyBuilder CreateProperty(string propertyName,Type propertyType,MethodAttributes getterAttributes,MethodAttributes setterAttributes,bool isReadOnly,bool isWriteonly,TypeBuilder builder)
    {
        PropertyBuilder result = null;
        if (builder != null && propertyType != null)
        {

            result = builder.DefineProperty(propertyName,PropertyAttributes.HasDefault,propertyType,null);
            FieldBuilder fieldBuilder = builder.DefineField("_" + propertyName,FieldAttributes.Private);
            if (!isWriteonly)
            {
                MethodBuilder getPropMthdBldr = builder.DefineMethod("get_" + propertyName,getterAttributes,Type.EmptyTypes);
                ILGenerator getIl = getPropMthdBldr.GetILGenerator();

                getIl.Emit(OpCodes.Ldarg_0);
                getIl.Emit(OpCodes.Ldfld,fieldBuilder);

                getIl.Emit(OpCodes.Ret);
                result.SetGetMethod(getPropMthdBldr);
            }
            if (!isReadOnly)
            {
                MethodBuilder setPropMthdBldr = builder.DefineMethod("set_" + propertyName,setterAttributes,null,new[] { propertyType });
                ILGenerator setIl = setPropMthdBldr.GetILGenerator();
                Label modifyProperty = setIl.DefineLabel();
                Label exitSet = setIl.DefineLabel();
                setIl.MarkLabel(modifyProperty);
                setIl.Emit(OpCodes.Ldarg_0);
                setIl.Emit(OpCodes.Ldarg_1);
                setIl.Emit(OpCodes.Stfld,fieldBuilder);
                setIl.Emit(OpCodes.Nop);
                setIl.MarkLabel(exitSet);
                setIl.Emit(OpCodes.Ret);
                result.SetSetMethod(setPropMthdBldr);
            }
        }
        return result;
    }

对我自己来说,一个完美的解决方案是,如果我可以将一个匿名方法传递给“ getProperty”,我将在getter中调用它。 (这是我的最终目标)。

但是我在getter内部的函数调用方面遇到了麻烦。 目前,我在静态类中使用静态函数作为调用。 我的创建属性函数当前如下所示:

        private PropertyBuilder CreateProperty(string propertyName,TypeBuilder builder)
    {
        PropertyBuilder result = null;
        if (builder != null && propertyType != null)
        {
            var mInfo = typeof(RuntimeInjection).GetMethod("ModifyString");
            result = builder.DefineProperty(propertyName,Type.EmptyTypes);
                ILGenerator getIl = getPropMthdBldr.GetILGenerator();
                //getIl.Emit(OpCodes.Nop);
                getIl.Emit(OpCodes.Ldarg_0);
                getIl.Emit(OpCodes.Ldfld,fieldBuilder);
                if (propertyType.Equals(typeof(string)))
                {
                    getIl.Emit(OpCodes.Call,mInfo);
                    getIl.Emit(OpCodes.Stloc_0);
                    getIl.Emit(OpCodes.Br_S);
                    getIl.Emit(OpCodes.Ldloc_0);
                }
                getIl.Emit(OpCodes.Ret);
                result.SetGetMethod(getPropMthdBldr);
            }
            if (!isReadOnly)
            {
                MethodBuilder setPropMthdBldr = builder.DefineMethod("set_" + propertyName,fieldBuilder);
                setIl.Emit(OpCodes.Nop);
                setIl.MarkLabel(exitSet);
                setIl.Emit(OpCodes.Ret);
                result.SetSetMethod(setPropMthdBldr);
            }
        }
        return result;
    }

这是我引用的功能(只是一个虚拟测试对象):

    public static class RuntimeInjection
{

    public static string ModifyString(string input)
    {
        return input;
    }

}

但是,每次测试时,都会出现错误:“ System.InvalidProgramException:“公共语言运行时检测到无效程序”。 仅当我访问get函数时,该错误才会发生。他能够生成类型,我也可以为属性分配值。

出现错误后,我尝试了多种方法。我写了一个类似的测试属性:

        public string Name
    {
        get
        {
            return Modify(_name);
        }
        set
        {
            _name = value;
        }
    }

然后我打开IL反汇编程序并签出命令。反汇编程序向我显示了此信息:

在运行时使用TypeBuilder创建类,并在属性getter中调用函数

我被困在这里,是因为散播者向我展示的内容与我大致相同。 需要一些新鲜的想法,也许您可​​以提供一些:)。

更新: 我想我发现了可能的问题。 IL_000e:brs。IL_0010

                        // I think Br_S needs a label to ldloc_0 but i am unsure how to do it. Anyone used Br_S already?
                    getIl.Emit(OpCodes.Br_S);
                    getIl.Emit(OpCodes.Ldloc_0);
yang130sam 回答:在运行时使用TypeBuilder创建类,并在属性getter中调用函数

暂时没有好的解决方案,如果你有好的解决方案,请发邮件至:iooj@foxmail.com
本文链接:https://www.f2er.com/3050501.html

大家都在问