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");
  • 相关阅读:
    vue父子组件通信
    canvas(一)
    js中的this
    git中遇到的问题
    javaScript中各种数据结构的遍历
    git合并多个提交
    vue学习笔记(三)——vuex—store配置
    vue学习笔记(二)——路由配置
    0欧电阻的作用
    STM32L系列单片机内部EEPROM的读写
  • 原文地址:https://www.cnblogs.com/jobs/p/22196.html
Copyright © 2011-2022 走看看