目标

我的目标是实现一个密封的公共(public)嵌套类,该类只能由其封闭类创建 - 不使用反射。

这意味着嵌套类不能有任何公共(public)或内部构造函数或任何公共(public)或内部静态工厂方法。

以前的工作

This post from a couple of years ago seems to be the answer 。 (整个线程有很多关于我想要实现的目标的信息。)

它的工作原理非常简单:它利用了嵌套类可以访问其封闭类的静态字段以及嵌套类的静态构造函数这一事实。

封闭类声明了一个静态 Func<NestedClassType, NestedClassCtorArgType> 委托(delegate),它返回嵌套类的实例,以便封闭类可以将该委托(delegate)用作工厂方法。

嵌套类本身有一个静态构造函数,它将封闭类的静态工厂委托(delegate)初始化为一个委托(delegate),该委托(delegate)将创建嵌套类的实例。

问题

不幸的是,我无法让它工作,因为它是写在那个答案中的。原因是嵌套类的静态构造函数在封闭类使用工厂方法之前没有被调用,因此存在空引用异常。 (如果您查看此问题末尾的示例程序,您就会明白我的意思。)

我的解决方法

我已经解决了这个问题,如下所示:

  • 向嵌套类添加了一个什么都不做的内部静态 Initialise() 方法。
  • 向封闭类添加了一个静态构造函数,它调用嵌套类的 Initialise() 方法。

  • 这工作正常,但它在 internal static void Initialise() 方法的形状上留下了一点痈。

    我的问题

    有没有办法避免这种做法?我不禁觉得我在上面链接的原始帖子中遗漏了一些东西。我误解了答案吗?

    在我调用尝试创建嵌套类的实例的代码之前,是否有一种聪明的方法可以强制运行嵌套类的静态构造函数?

    这种方法还有其他问题吗?

    (我知道我可以为嵌套类编写一个公共(public)接口(interface),然后返回它。这个问题不是关于以这种方式解决的!)

    示例代码

    这是我的示例代码。尝试运行它,它会打印“Test”。然后尝试注释掉标记为 <--- If you comment this out, things won't work 的行并再次运行它。
    using System;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main()
            {
                Outer outer = new Outer();
                Outer.Inner item = outer.Item("Test");
                Console.WriteLine(item.Text);
            }
        }
    
        public sealed class Outer
        {
            public Inner Item(string text)
            {
                return _nestedFactory(text);
            }
    
            // This static constructor calls the nested class's Initialise() method, which causes the
            // nested class's static constructor to run, which then sets the enclosing class's
            // _nestedFactory field appropriately.
    
            static Outer()
            {
                Inner.Initialise(); // <--- If you comment this out, things won't work.
            }
    
            // This class has a private constructor.
            // I only want class Outer to be able to create instances of it.
    
            public sealed class Inner
            {
                private Inner(string value) // Secret private constructor!
                {
                    text = value;
                }
    
                public string Text { get { return text; } }
    
                static Inner()
                {
                    _nestedFactory = text => new Inner(text);
                }
    
                internal static void Initialise(){}
                readonly string text;
            }
    
            static Func<string, Inner> _nestedFactory;
        }
    }
    

    最佳答案

    如果您需要强制运行类构造函数而不引用类型,则可以使用此代码:

    static Outer()
    {
        System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof (Inner).TypeHandle);
    }
    

    关于c# - 如何实现只能由其封闭类创建的密封公共(public)嵌套类?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16339237/

    10-11 15:11