zoukankan      html  css  js  c++  java
  • 如何调用只有私有构造函数的类

    当我试用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");
  • 相关阅读:
    VC++用Recordset MSPersist载入C#DataSet Save出来的xml失败,但载入VC Recordset Save出来的xml则没问题,怎么xml不通用呢?
    观察力、分析问题的能力、与人沟通的能力和资源整合能力
    [导入]有感于神童之神源
    军训系列二:两类人创业不容易成功
    运行微软的SOAP3.0的VC样例Samples30_ADOTM_Client报错,m_pSoapClient>Invoke时直接失败
    About IM software
    [导入][转]好企业是什么样?
    动网论坛v7.0.0SQL版竟然帯病毒!
    CZoneSoft出品: 音频视频在线录制系列之 AV留言本 简介
    递归算法在生成树型结构中,几乎完全属于无稽的算法
  • 原文地址:https://www.cnblogs.com/jobs/p/22196.html
Copyright © 2011-2022 走看看