确保A类只能由B类创建

时间:2013-01-24 16:22:16

标签: c# constructor factory

我已经在SO(和其他地方)上阅读了关于这个主题的一些讨论,但没有能够收集到明确的答案。

我想确保给定的A类只能由特定的类B创建。在C ++中,我将A的构造函数设为private,并将B指定为朋友。现在只有B可以创建A.

在C#中这样做的惯用方法是什么,如果确实有一个呢?

4 个答案:

答案 0 :(得分:6)

您可以使用私有内部类。

但是,这种用途有限。

class B
{
  private class A
  {
  }
}

答案 1 :(得分:3)

你不能在C#中使用C ++风格的方法。

我之前遇到过这种情况,我通常通过使类A abstract(需要继承)和构造函数protected来解决它(只有继承自类的类才能调用构造函数)。

然后我在类B中创建一个private类(称为'_A'),并从A继承。(_A中没有其他代码。)_A定义一个公共的构造函数 - 因此对B可见(仅限B,因为_A是私有的)。

在B中,您可以创建_A的实例并将其作为A返回(通过polymorphism)。

我更喜欢这种公共接口的方法,因为如果在其中实现类A,我的B类代码文件会变得非常庞大。这只是我的偏好 - 其他人可能会有不同的意见。

abstract class A
{

    protected A()
    {
    }

    /* implementation details... */

}

public class B
{

    public A GetInstance()
    {
        return new _A();
    }

    private class _A : A
    {

        public _A()
        {
        }

    }

}

答案 2 :(得分:1)

我假设外部代码需要引用A,但不应该能够创建实例。

没有简单的方法可以实现这一目标。如果你创建A的构造函数internal,那么只有与A相同的程序集中的代码才能构造它(不使用反射)。

可以创建StackTrace的实例并检查索引1处的框架以查看它是否来自B的方法,但这可能会导致性能问题,并且是一种黑客攻击。

答案 3 :(得分:1)

这是可行的,但是以一种讨厌的方式。可能在C ++中更令人讨厌的“朋友”概念。

您可以声明私有构造函数和静态工厂方法,您只允许特定类型调用此方法(通过检查StackFrame)。

public class Foo
{
  private Foo() { }

  public static Foo Create()
  {
    if(GetCallingType() != typeof(Bar))
    {
      throw new Exception("Only Bar can create Foo");
    }
    return new Foo();
  }

  private static Type GetCallingType()
  {
    return new StackFrame(2, false).GetMethod().DeclaringType;
  }
}