2009-11-13 9 views
5

Esta pregunta es similar a clase abstracta interna C#, cómo ocultar el uso fuera pero mi motivación es diferente. Aquí está el panoramaCómo limitar la creación de subclase de clase abstact pública a tipos en el mismo ensamblado y así permitir miembros protegidos escritos a tipos internos

Empecé con lo siguiente:

internal class InternalTypeA {...} 

public class PublicClass 
{ 
    private readonly InternalTypeA _fieldA; 

    ... 
} 

Lo anterior compila bien. Pero luego decidí que debería extraer una clase base y trataba de escribir el siguiente:

public abstract class PublicBaseClass 
{ 
    protected readonly InternalTypeA _fieldA; 

    ... 
} 

Y así el problema, el miembro protegido es visible fuera de la Asamblea, pero es de un tipo interno, para que no se compilar.

El problema en cuestión es cómo puedo (¿o puedo?) Decirle al compilador que solo las clases públicas en el mismo ensamblaje que PublicBaseClass pueden heredar de él y por lo tanto _fieldA no se expondrá fuera del ensamblado?

¿O hay otra manera de hacer lo que quiero hacer, tener una súper clase pública y un conjunto de clases base públicas que están todas en el mismo ensamblado y usar tipos internos de ese ensamblado en su común ("protegido" ¿código?

La única idea que he tenido hasta ahora es la siguiente:

public abstract class PublicBaseClass 
{ 
    private readonly InternalTypeA _fieldA; 

    protected object FieldA { get { return _fieldA; } } 

    ... 
} 

public class SubClass1 : PublicBaseClass 
{ 
    private InternalTypeA _fieldA { get { return (InternalTypeA)FieldA; } } 
} 

public class SubClass2 : PublicBaseClass 
{ 
    private InternalTypeA _fieldA { get { return (InternalTypeA)FieldA; } } 
} 

Pero eso es FEO!

Respuesta

5

El CLR proporciona una accesibilidad de FamilyAndAssembly que hará lo que usted desee, pero no existe la sintaxis en C# para usarlo.

La solución consiste en hacer que el campo variable sea interno, y tendrá que confiar en el código de su ensamblado para no tener acceso a él de manera inapropiada.

También puede hacer que el constructor de PublicBaseClass sea interno, por lo que solo su ensamblaje puede instanciarlo. De esta manera, solo sus clases pueden heredar (incluso si la clase es pública)

+1

Sí, FamilyAndAssembly es exactamente lo que quiero. Acepto que usar miembros internos es mejor que mi hack anterior. Me pregunto por qué no pensé en eso. Probablemente porque odio tanto el alcance del alcance de las cosas. ¡Gracias por la información! –

+0

Ay, también me parece bastante molesto, pero es algo con lo que tenemos que vivir, desafortunadamente :( – thecoop

0

La forma más limpia de lidiar con esto es el uso de interfaces públicas y clases privadas. Si refactoriza el código existente, esto no siempre es una opción. Una manera fácil de aliviar el dolor de esa conversión es usar una clase abstracta pública en lugar de una interfaz y exponer un método de fábrica estático.

Ejemplo:

public abstract class MyClass 
{ 
    public static MyClass New() 
    { return new InternalMyClass(); } 
} 

class InternalMyClass : MyClass 
{ } 
+0

Este enfoque no funcionaría porque necesito que InternalMyClass sea de tipo público. –

Cuestiones relacionadas