现在的位置: 首页 > 综合 > 正文

如何调用只有私有构造函数的类

2012年05月15日 ⁄ 综合 ⁄ 共 2386字 ⁄ 字号 评论关闭

当我试用ObjectSpaces时,ObjectSpaces竟然能够调用只有私有构造函数的类。例如:

Class 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);

以上是思路,我们也来写一段代码,让其能够调用缺省构造函数创建对象实例,具体代码:

第一步, 定义一个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>));
}


第三步,定义创建实例的方法:

public T CreateInstance<T>()
{
CreateInstanceDelegate
<T> createInstDelegate = BuildDelegate<T>();
return createInstDelegate();
}

第四步,如此使用:
定义一个私有缺省构造函数的类

class A
{
private A() {}
}

创建实例的代码:

A a = CreateInstance<A>();
Console.WriteLine(
"create A instance");

抱歉!评论已关闭.