2012-09-19 12 views
6

Ho una libreria di classi con 2 classi pubbliche che ereditano da una classe astratta. Nella classe astratta ho un campo protetto che dovrebbe essere accessibile solo alle classi ereditate. Il tipo utilizzato per il campo è quello di una classe interna.Utilizzo di un tipo interno utilizzato come campo protetto

Per esempio io ho:

internal class MyInternalClass 
{ 
    ... 
} 

public abstract class MyAbstractClass 
{ 
    protected MyInternalClass myField; 
} 

Adesso ho capito che questo non funzionerà, perché se una delle classi che derivano dalla classe MyAbstract si estende al di fuori del gruppo, l'accesso a myField sarebbe illegale.

La mia domanda è: come posso far funzionare le cose mantenendo MyInternalClass interno (non dovrebbe essere accessibile al di fuori dell'assieme) e consentendo alle classi all'interno dell'assieme di estendere MyAbstractClass con accesso a myField?

+4

La seconda classe ('abstract') deve essere' public'? –

+0

Sì, deve essere. Le 2 classi che lo estendono sono pubbliche. – zaq

+0

possibile duplicato di [Come rendere una proprietà protetta E interna in C#?] (Http: // stackoverflow.it/questions/941104/how-to-make-a-property-protected-and-internal-in-c) – nawfal

risposta

5

Creare un'interfaccia pubblica che richiede MyAbstractClass e MyInternalClass attrezzi.

Qualcosa di simile a questo modo si può avere essere MyInternalClass di default, ma iniettare nuovo comportamento se si ha bisogno (ad esempio, beffardo):

internal class MyInternalClass : IMyInterface 
{ 
} 

public interface IMyInterface 
{    
} 

public abstract class MyAbstractClass 
{ 
    protected IMyInterface myField; 

    protected MyAbstractClass(IMyInterface required = null) 
    { 
     myField = required ?? new MyInternalClass(); 
    } 
} 
+2

È anche possibile memorizzare il riferimento di classe interno in un campo privato, quindi fornire una proprietà protetta esponendolo come pubblico interfaccia. Questo ha il vantaggio collaterale di consentire di limitare ulteriormente l'accesso alla classe interna (tramite l'interfaccia) solo a ciò che è necessario per i deriver di MyAbstractClass. Offre inoltre flessibilità se questa interfaccia viene implementata in modo diverso (ad esempio scomporne le funzionalità in due classi helper anziché una, ad esempio). –

+0

@DanBryant: molto vero. Buon suggerimento –

0

Non è possibile. Se MyAbstractClass deriva da una classe esterna, è necessario conoscere MyInternalClass.

Se hai bisogno di pensare a cose come questa, il design potrebbe aver bisogno di rielaborazione.

0

Fare il campo myFieldinternal protected.

È inoltre necessario rendere MyAbstractClass interno. Non c'è modo che possa essere pubblico se eredita da una classe interna. Se la classe deve essere pubblica, deve esserci un modo per aggirare il problema: ad esempio, creare un'interfaccia che esponga la funzionalità di MyInternalClass di cui hanno bisogno le classi ereditanti.

0

hai bisogno di una parola chiave che specifica protetta "e" interno invece di protetta "o" interna. Tale parola chiave non esiste (a partire da C# 5.0). Potrebbero aggiungerlo nelle versioni successive.

Ci sono molti thread su questo qui. Ad esempio, question 5596338.

AGGIUNTA: ora ho escogitato questa "soluzione":

public abstract class MyAbstractClass 
{ 
    protected class AccessMyFieldHelper 
    { 
     internal MyInternalClass this[MyAbstractClass mac] 
     { 
      get { return mac.myField; } 
      set { mac.myField = value; } 
     } 
    } 
    protected static readonly AccessMyFieldHelper AccessMyField = new AccessMyFieldHelper(); 

    private MyInternalClass myField; 
} 

Il myField è ora private, ma non v'è protetto l'accesso ad esso attraverso il AccessMyField. Poiché si tratta di un indicizzatore, sarà necessario utilizzare le parentesi quadre [].

Cosa ne pensi? Questo può essere fatto in modo più bello?

Problemi correlati