繁体   English   中英

动态类型阴影基类的属性并使用 Reflection.Emit 设置为 protected

[英]Dynamic type shadow base class's property and set to protected using Reflection.Emit

我工作了几天尝试隐藏基类的属性并使用 Reflection.Emit 将派生类属性设置为保护。 当我创建一个派生类并将 new 设置为基属性时,调用 GetProperties() 它只显示一个具有名称的属性,并且派生类属性不是公共的,但是动态类型调用 GetProperties() 显示两个具有相同名称的属性出现(基本属性是公共的,动态类型不是公共的)。 这是我的代码。

namespace ILHiddenProperty
{
    interface IILName
    {
        string Name { get; set; }
    }

    public class ClassName : IILName
    {
        public string Name { get; set; } = "ClassName";
    }

    public class ChildName : ClassName
    {
        protected new string Name { get; set; } = "ChildName";
    }

    public class NameILGenerator
    {
        public static Type ILType()
        {
            AssemblyName aname = new AssemblyName("MyAssembly");
            AppDomain currentDomain = AppDomain.CurrentDomain; // Thread.GetDomain();
            AssemblyBuilder asmbuilder = currentDomain.DefineDynamicAssembly(aname,
                                       AssemblyBuilderAccess.Run);
            ModuleBuilder mbuilder = asmbuilder.DefineDynamicModule("EmitMethods");
            TypeBuilder tbuilder = mbuilder.DefineType("ILName", TypeAttributes.Public,typeof(ClassName)); 
            FieldBuilder fName = tbuilder.DefineField("_name", typeof(System.String), FieldAttributes.Private);
            PropertyBuilder pName = tbuilder.DefineProperty("Name", PropertyAttributes.HasDefault, typeof(System.String), null);
            //Getter
            MethodBuilder mNameGet = tbuilder.DefineMethod("get_Name", MethodAttributes.Family | 
                MethodAttributes.SpecialName | 
                MethodAttributes.HideBySig, 
                typeof(System.String), 
                Type.EmptyTypes);
            ILGenerator nameGetIL = mNameGet.GetILGenerator();
            nameGetIL.Emit(OpCodes.Ldarg_0);
            nameGetIL.Emit(OpCodes.Ldfld, fName);
            nameGetIL.Emit(OpCodes.Ret);

            //Setter
            MethodBuilder mNameSet = tbuilder.DefineMethod("set_Name", MethodAttributes.Family | 
                MethodAttributes.SpecialName | 
                MethodAttributes.HideBySig, 
                null, 
                new Type[] { typeof(System.String) });

            ILGenerator nameSetIL = mNameSet.GetILGenerator();

            nameSetIL.Emit(OpCodes.Ldarg_0);
            nameSetIL.Emit(OpCodes.Ldarg_1);
            nameSetIL.Emit(OpCodes.Stfld, fName);
            nameSetIL.Emit(OpCodes.Ret);

            pName.SetGetMethod(mNameGet);
            pName.SetSetMethod(mNameSet);
            return tbuilder.CreateType();
        }
    }
}
namespace ILHiddenProperty
{
    class Program
    {
        static void Main(string[] args)
        {
            PrintNameProperty(typeof(ClassName));
            PrintNameProperty(typeof(ChildName));
            PrintNameProperty(NameILGenerator.ILType());
            Console.Read();
        }

        public static void PrintNameProperty(Type nameType)
        {
            var props = nameType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
            foreach(var prop in props)
            {
                Console.WriteLine("{0}.{1} IsPublic:{2}",nameType.Name, prop.Name, prop.GetMethod.IsPublic);
            }
        }
    }
}

我尝试添加 MethodAttributes.NewSlot 它没有用。 当我将 MethodAttributes.Family 更改为 MethodAttributes.Public 时,会出现 AmbiguousMatchException。

用 Reflection.Emit搜索了这个 Overriding 属性定义,并将 ILType 更改为不定义属性而只定义 get 和 set 函数

        public static Type ILType()
        {
            AssemblyName aname = new AssemblyName("MyAssembly");
            AppDomain currentDomain = AppDomain.CurrentDomain; // Thread.GetDomain();
            AssemblyBuilder asmbuilder = currentDomain.DefineDynamicAssembly(aname,
                                       AssemblyBuilderAccess.Run);
            ModuleBuilder mbuilder = asmbuilder.DefineDynamicModule("EmitMethods");
            TypeBuilder tbuilder = mbuilder.DefineType("ILName", TypeAttributes.Public,typeof(ClassName)); 
            FieldBuilder fName = tbuilder.DefineField("_name", typeof(System.String), FieldAttributes.Private);
            //PropertyBuilder pName = tbuilder.DefineProperty("Name", PropertyAttributes.HasDefault, typeof(System.String), null);
            //Getter
            MethodBuilder mNameGet = tbuilder.DefineMethod("get_Name", MethodAttributes.Family | 
                MethodAttributes.SpecialName | 
                MethodAttributes.HideBySig, 
                typeof(System.String), 
                Type.EmptyTypes);
            ILGenerator nameGetIL = mNameGet.GetILGenerator();
            nameGetIL.Emit(OpCodes.Ldarg_0);
            nameGetIL.Emit(OpCodes.Ldfld, fName);
            nameGetIL.Emit(OpCodes.Ret);

            //Setter
            MethodBuilder mNameSet = tbuilder.DefineMethod("set_Name", MethodAttributes.Family | 
                MethodAttributes.SpecialName | 
                MethodAttributes.HideBySig, 
                null, 
                new Type[] { typeof(System.String) });

            ILGenerator nameSetIL = mNameSet.GetILGenerator();

            nameSetIL.Emit(OpCodes.Ldarg_0);
            nameSetIL.Emit(OpCodes.Ldarg_1);
            nameSetIL.Emit(OpCodes.Stfld, fName);
            nameSetIL.Emit(OpCodes.Ret);

            //pName.SetGetMethod(mNameGet);
            //pName.SetSetMethod(mNameSet);
            return tbuilder.CreateType();
        }

它显示了一个属性,但该属性是公共的。 那么如何将属性设置为受保护?

固定的
  • 获取方法返回String类型

您应该在定义属性时使用CallingConventions.HasThis

tbuilder.DefineProperty("Name", 
                        PropertyAttributes.HasDefault, 
                        CallingConventions.HasThis,
                        typeof(System.String), 
                        null);

您可以在此处获得更多信息: HasThis 和 ExplicitThis 调用约定

顺便说一句,创建类型后调用asmBuilder.Save("xxx.dll")帮助。 它允许您获取程序集文件并使用 ILSpy 对其进行反编译。 在调用DefineDynamicAssembly时必须使用AssemblyBuilderAccess.RunAndSave并在调用DefineDynamicModule时指定fileName

您的代码中还有一个错误,您的 getter 返回一个Int32而该属性的类型为String

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM