代码之家  ›  专栏  ›  技术社区  ›  mezoid

如何在Silverlight中实例化只有私有无参数构造函数的类?

  •  1
  • mezoid  · 技术社区  · 14 年前

    我正在为.NET测试数据生成器处理一个功能请求。我需要能够实例化只有私有无参数构造函数的类。

    例如,我可能需要实例化以下类:

    public class MyClass()
    {
        private MyClass(){}
    }
    

    对于大多数其他类,我使用以下代码:

    (T)Activator.CreateInstance(typeof(T), true)
    

    但是对于只有私有无参数构造函数的类,我使用以下方法:

    (T)FormatterServices.GetUninitializedObject(typeof(T))
    

    不幸的是,我还要求这在Silverlight中有效,不幸的是Silverlight当前不包含System.Runtime.Serialization.FormatterServices。

    是否有人知道Silverlight实现中允许我绕过此问题的任何内容?如果失败了,有人知道我如何实现这个方法的自己版本吗?

    3 回复  |  直到 14 年前
        1
  •  1
  •   Jon Skeet    14 年前

    不能从类外部实例化该类。大概是故意的 设计 所以你不能实例化它。

    我希望有一些静态的方法来获取实例,例如单例属性或工厂方法…但是如果你需要这样做 任何 类型,那不管用。

    基本上,你需要重新考虑你的设计-不要试图颠覆课堂作者的意愿。

        2
  •  1
  •   Community CDub    8 年前

    结果,答案就在我面前。

    如果有一个类定义如下:

    public class MyClass
    {
        private MyClass(){}
    }
    

    您可以使用我在问题中提到的以下代码来实例化它:

    (T)Activator.CreateInstance(typeof(T), true)
    

    附加参数true,使用 type's default constructor .

    结果,我甚至不需要首先使用FormatterServices.GetUninitializedObject。

    不过,我要感谢乔恩·斯基特的回答,因为这有助于我质疑我的设计,深入了解activator.createInstance,并稍微提高我对类实例化的理解。

    目前,我的解决方案是删除对FormatterServices的使用,并只允许在类型创建出现问题时抛出异常。

    目前,根据我所知,使用(t)activator.createInstance(typeof(t),true),我应该能够构建我遇到的大多数类,除了以下类:

    public MyClass()
    {
        int a;
        private MyClass(int a)
        {
            this.a = a;
        }
    }
    

    然而,事实证明有一种建议 here 要能够实例化此类:

    int argA = 100; 
    Type type = typeof(MyClass);
    
    ConstructorInfo c = type.GetConstructor(BindingFlags.NonPublic 
    | BindingFlags.Instance, null, new Type[] { typeof(int) }, null);
    
    MyClass o = (MyClass)c.Invoke(new Object[] { argA });
    

    但是在考虑了Jon所说的内容之后,我认为这对于使用我正在增强的测试数据生成器的任何人都没有多大用处。如果有人为了阻止类被实例化而陷入了如此大的麻烦,那么也许除了通过类设计器提供的方法之外,它不应该被构造。

        3
  •  0
  •   Francesco De Vittori    14 年前

    你可以用反射来做, 但是

    • 你真的应该决定你是否做了正确的事情。正如其他人所说,类的设计可能不会以这种方式实例化。然而,我理解在一些罕见的情况下,这可能是必需的。

    • 您需要完全信任地运行它,即在浏览器外运行。您不能在浏览器中执行此操作。

    代码如下:

    var privateConstructors = typeof(MyClass).GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance);
    foreach (var constr in privateConstructors)
    {
        var obj = constr.Invoke(new object[0]);
        return;
    }
    throw new Exception("private constructor not found");