动态类型 shadow base class 的 属性 并使用 Reflection.Emit 设置为受保护
Dynamic type shadow base class's property and set to protected using Reflection.Emit
我工作了几天,尝试隐藏基础 class 的 属性 并将派生的 class 属性 设置为使用 Reflection.Emit 保护。当我创建派生 class 并将新设置为基础 属性 时,调用 GetProperties() 它只显示一个 属性 名称和派生 class 属性 不是 public,但是动态类型调用 GetProperties() 显示出现了两个同名的属性(基础 属性 是 public 而动态类型不是 public)。这是我的代码。
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。
我搜索了这个 Overriding property definitions with Reflection.Emit 并将 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();
}
它显示一个 属性 但 属性 是 Public。那么如何将 属性 设置为受保护?
固定的
- return 类型
String
的获取方法
定义 属性 时应使用 CallingConventions.HasThis
:
tbuilder.DefineProperty("Name",
PropertyAttributes.HasDefault,
CallingConventions.HasThis,
typeof(System.String),
null);
您可以在此处获得更多信息:
顺便说一句,创建类型后调用 asmBuilder.Save("xxx.dll")
会有所帮助。它允许您获取程序集文件并使用 ILSpy 对其进行反编译。您必须在调用 DefineDynamicAssembly
时使用 AssemblyBuilderAccess.RunAndSave
并在调用 DefineDynamicModule
.
时指定 fileName
您的代码中还有一个错误,您的 getter return 和 Int32
而 属性 的类型是 String
我工作了几天,尝试隐藏基础 class 的 属性 并将派生的 class 属性 设置为使用 Reflection.Emit 保护。当我创建派生 class 并将新设置为基础 属性 时,调用 GetProperties() 它只显示一个 属性 名称和派生 class 属性 不是 public,但是动态类型调用 GetProperties() 显示出现了两个同名的属性(基础 属性 是 public 而动态类型不是 public)。这是我的代码。
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。
我搜索了这个 Overriding property definitions with Reflection.Emit 并将 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();
}
它显示一个 属性 但 属性 是 Public。那么如何将 属性 设置为受保护?
固定的- return 类型
String
的获取方法
定义 属性 时应使用 CallingConventions.HasThis
:
tbuilder.DefineProperty("Name",
PropertyAttributes.HasDefault,
CallingConventions.HasThis,
typeof(System.String),
null);
您可以在此处获得更多信息:
顺便说一句,创建类型后调用 asmBuilder.Save("xxx.dll")
会有所帮助。它允许您获取程序集文件并使用 ILSpy 对其进行反编译。您必须在调用 DefineDynamicAssembly
时使用 AssemblyBuilderAccess.RunAndSave
并在调用 DefineDynamicModule
.
fileName
您的代码中还有一个错误,您的 getter return 和 Int32
而 属性 的类型是 String