允许访问但阻止外部类实例化嵌套类

时间:2012-10-19 13:09:31

标签: c# encapsulation inner-classes nested-class

我正在寻找一个容器类和外部类可以访问的嵌套类,但我想控制嵌套类的实例化,这样只有容器类的实例才能创建嵌套类的新实例

诉讼代码应该有希望证明这一点:

public class Container
{
    public class Nested
    {
        public Nested() { }
    }

    public Nested CreateNested()
    {
        return new Nested();  // Allow
    }
}

class External
{
    static void Main(string[] args)
    {
        Container containerObj = new Container();
        Container.Nested nestedObj;

        nestedObj = new Container.Nested();       // Prevent
        nestedObj = containerObj.CreateNested();  // Allow

    }
}

Nested必须公开,以便External可以访问它。我尝试使Nested的构造函数受到保护,但这会阻止Container创建实例,因为Container不是Nested的基类。我可以将Nested的构造函数设置为internal,但我希望阻止所有外部类(包括同一程序集中的那些外部类)访问构造函数。有没有办法做到这一点?

如果无法通过访问修饰符实现这一点,我想知道是否可以在Nested()内抛出异常。但是,我不知道如何测试调用new Nested()的上下文。

2 个答案:

答案 0 :(得分:7)

如何通过界面进行抽象?

public class Container
{
    public interface INested
    {
        /* members here */
    }
    private class Nested : INested
    {
        public Nested() { }
    }

    public INested CreateNested()
    {
        return new Nested();  // Allow
    }
}

class External
{
    static void Main(string[] args)
    {
        Container containerObj = new Container();
        Container.INested nestedObj;

        nestedObj = new Container.Nested();       // Prevent
        nestedObj = containerObj.CreateNested();  // Allow

    }
}

您也可以使用抽象基类做同样的事情:

public class Container
{
    public abstract class Nested { }
    private class NestedImpl : Nested { }
    public Nested CreateNested()
    {
        return new NestedImpl();  // Allow
    }
}

class External
{
    static void Main(string[] args)
    {
        Container containerObj = new Container();
        Container.Nested nestedObj;

        nestedObj = new Container.Nested();       // Prevent
        nestedObj = containerObj.CreateNested();  // Allow

    }
}

答案 1 :(得分:1)

以这种方式申报课是不可能的。我认为最好的方法是将class声明为private并通过公共接口公开它:

class Program
{
    static void Main(string[] args)
    {
       // new S.N(); does not work
        var n = new S().Create();
    }
}

class S
{
    public interface IN
    {
        int MyProperty { get; set; }
    }
    class N : IN
    {
        public int MyProperty { get; set; }
        public N()
        {

        }
    }

    public IN Create()
    {
        return new N();
    }
}