9

I'm looking to define a nested class that is accessible to the container class and external classes, but I want to control instantiation of the nested class, such that only instances of the container class can create new instances of the nested class.

The proceeding code should hopefully demonstrate this:

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 must be public in order for it to be accessible by External. I tried making the constructor for Nested protected, however that prevents Container from creating instances, as Container isn't a base class of Nested. I could set the constructor for Nested to internal, but I'm looking to prevent access to the constructor by all external classes, including those in the same assembly. Is there a way to do this?

If this cannot be achieved through access modifiers, I wonder if I could throw an exception within Nested(). However, I don't know how to test for the context within which new Nested() is called.

4

2 回答 2

11

通过接口进行抽象怎么样?

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

    }
}
于 2012-10-19T13:16:26.233 回答
1

以这种方式声明类是不可能的。我认为对您来说最好的方法是将类声明为私有并通过公共接口公开它:

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();
    }
}
于 2012-10-19T13:16:58.060 回答