当我试用ObjectSpaces时,ObjectSpaces竟然能够调用只有私有构造函数的类。例如:
Class A
{
private A() {}
}
{
private A() {}
}
ObjectSpaces能够创建A的实例,我刚看到的时候,吃了一惊,呵呵…… 后来,借助Reflector分析整理学会了此技巧。
你不能通过Reflection直接创建只有私有构造函数的类,但是你可以通过一些偏门技巧绕过此限制。
其大概思路这样的:
private CreateInstanceDelegate<T> BuildDelegate<T>()
{
Type type = typeof(T);
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = "System.Data.ObjectSpaces.Dynamic";
AssemblyBuilder assemblyBuilder
= AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
Module module
= assemblyBuilder.DefineDynamicModule("WebData", "DynamicAssembly.dll", true);
Type[] paramTypeArray = new Type[] {};
Type rtnType = type;
String methodName = "call_privateCtor";
bool skipVisibility = true;
DynamicMethod method = new DynamicMethod(
methodName,
rtnType,
paramTypeArray,
module,
skipVisibility
);
ConstructorInfo ctor = type.GetConstructor(
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
null,
new Type[0],
null
);
ILGenerator ilGen = method.GetILGenerator();
ilGen.Emit(OpCodes.Newobj, ctor);
ilGen.Emit(OpCodes.Ret);
{
Type type = typeof(T);
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = "System.Data.ObjectSpaces.Dynamic";
AssemblyBuilder assemblyBuilder
= AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
Module module
= assemblyBuilder.DefineDynamicModule("WebData", "DynamicAssembly.dll", true);
Type[] paramTypeArray = new Type[] {};
Type rtnType = type;
String methodName = "call_privateCtor";
bool skipVisibility = true;
DynamicMethod method = new DynamicMethod(
methodName,
rtnType,
paramTypeArray,
module,
skipVisibility
);
ConstructorInfo ctor = type.GetConstructor(
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
null,
new Type[0],
null
);
ILGenerator ilGen = method.GetILGenerator();
ilGen.Emit(OpCodes.Newobj, ctor);
ilGen.Emit(OpCodes.Ret);
以上是思路,我们也来写一段代码,让其能够调用缺省构造函数创建对象实例,具体代码:
第一步, 定义一个Delegate:
public delegate T CreateInstanceDelegate<T>();
第二步,定义构建Delegate的方法,关键在此:
private CreateInstanceDelegate<T> BuildDelegate<T>()
{
Type type = typeof(T);
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = "System.Data.ObjectSpaces.Dynamic";
AssemblyBuilder assemblyBuilder
= AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
Module module
= assemblyBuilder.DefineDynamicModule("WebData", "DynamicAssembly.dll", true);
Type[] paramTypeArray = new Type[] {};
Type rtnType = type;
String methodName = "call_privateCtor";
bool skipVisibility = true;
DynamicMethod method = new DynamicMethod(
methodName,
rtnType,
paramTypeArray,
module,
skipVisibility
);
ConstructorInfo ctor = type.GetConstructor(
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
null,
new Type[0],
null
);
ILGenerator ilGen = method.GetILGenerator();
ilGen.Emit(OpCodes.Newobj, ctor);
ilGen.Emit(OpCodes.Ret);
return (CreateInstanceDelegate<T>) method.CreateDelegate(typeof(CreateInstanceDelegate<T>));
}
{
Type type = typeof(T);
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = "System.Data.ObjectSpaces.Dynamic";
AssemblyBuilder assemblyBuilder
= AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
Module module
= assemblyBuilder.DefineDynamicModule("WebData", "DynamicAssembly.dll", true);
Type[] paramTypeArray = new Type[] {};
Type rtnType = type;
String methodName = "call_privateCtor";
bool skipVisibility = true;
DynamicMethod method = new DynamicMethod(
methodName,
rtnType,
paramTypeArray,
module,
skipVisibility
);
ConstructorInfo ctor = type.GetConstructor(
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
null,
new Type[0],
null
);
ILGenerator ilGen = method.GetILGenerator();
ilGen.Emit(OpCodes.Newobj, ctor);
ilGen.Emit(OpCodes.Ret);
return (CreateInstanceDelegate<T>) method.CreateDelegate(typeof(CreateInstanceDelegate<T>));
}
第三步,定义创建实例的方法:
public T CreateInstance<T>()
{
CreateInstanceDelegate<T> createInstDelegate = BuildDelegate<T>();
return createInstDelegate();
}
{
CreateInstanceDelegate<T> createInstDelegate = BuildDelegate<T>();
return createInstDelegate();
}
第四步,如此使用:
定义一个私有缺省构造函数的类
class A
{
private A() {}
}
{
private A() {}
}
创建实例的代码:
A a = CreateInstance<A>();
Console.WriteLine("create A instance");
Console.WriteLine("create A instance");