目标
我的目标是实现一个密封的、公共的嵌套类,它只能由其封闭类创建——不使用反射。
这意味着嵌套类不能有任何公共或内部构造函数或任何公共或内部静态工厂方法。
之前的工作
几年前的这篇文章似乎是答案。(整个线程有很多关于我想要实现的目标的信息。)
它的工作原理非常简单:它利用嵌套类可以访问其封闭类的静态字段这一事实,以及嵌套类的静态构造函数。
封闭类声明了一个静态Func<NestedClassType, NestedClassCtorArgType>
委托,该委托返回嵌套类的一个实例,以便封闭类可以将该委托用作工厂方法。
嵌套类本身有一个静态构造函数,它将封闭类的静态工厂委托初始化为将创建嵌套类实例的委托。
问题
不幸的是,我无法让它工作,因为它写在那个答案中。原因是嵌套类的静态构造函数在封闭类使用工厂方法之前没有被调用,因此存在空引用异常。(如果您查看此问题末尾的示例程序,您会明白我的意思。)
我的解决方法
我已经解决了以下问题:
Initialise()
向嵌套类添加了一个不执行任何操作的内部静态方法。- 向封闭类添加了一个静态构造函数,该构造函数调用嵌套类的
Initialise()
方法。
这很好用,但它会留下一些internal static void Initialise()
方法形状的痈。
我的问题
有没有办法避免这种方式?我不禁认为我在上面链接的原始帖子中遗漏了一些东西。我误解了答案吗?
在我调用尝试创建嵌套类实例的代码之前,是否有一种聪明的方法可以强制运行嵌套类的静态构造函数?
这种方法还有其他问题吗?
(我知道我可以为嵌套类编写一个公共接口,然后将其返回。这个问题不是要以这种方式解决它!)
示例代码
这是我的示例代码。尝试运行它,它会打印“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;
}
}