2012-10-19 8 views
5

Czekam na zdefiniowanie klasy zagnieżdżonej, która jest dostępna dla klasy kontenera i klas zewnętrznych, ale chcę kontrolować tworzenie instancji klasy zagnieżdżonej, tak aby tylko wystąpienia klasy kontenera mogą tworzyć nowe instancje klasy zagnieżdżonej.Zezwalaj na dostęp, ale zapobiegaj instancjonowaniu klasy zagnieżdżonej przez klasy zewnętrzne

Kod postępowanie powinno wykazać to z nadzieją:

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 muszą być publiczne, aby mogła ona być dostępna przez External. Podjęto próbę zabezpieczenia konstruktora pod kątem ochrony przed Nested, ale uniemożliwia to tworzenie instancji przez Container, ponieważ Container nie jest klasą podstawową z Nested. Mogę ustawić konstruktora na Nested na internal, ale szukam, aby uniemożliwić dostęp do konstruktora przez wszystkie klasy zewnętrzne, w tym te w tym samym zestawie. Czy jest jakiś sposób na zrobienie tego?

Jeśli nie można tego osiągnąć za pomocą modyfikatorów dostępu, zastanawiam się, czy mogę rzucić wyjątek w ramach Nested(). Jednak nie wiem, jak przetestować kontekst, w którym jest wywoływana new Nested().

Odpowiedz

6

Co powiecie na abstrakcję za pośrednictwem interfejsu?

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 

    } 
} 

Można również zrobić to samo z abstrakcyjnego bazowej klasy:

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 

    } 
} 
+0

Wydaje się działać! Dzięki! –

1

Jest niemożliwe, aby zadeklarować klasę w taki sposób. Sądzę, że najlepszym sposobem na to, byś uznał klasę za prywatną i udostępnić ją publicznie:

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(); 
    } 
} 
Powiązane problemy