2010-04-08 4 views
6

J'ai trois classes; Classes A et B les deux classe de référence C.C# - Rendre les champs/propriétés en lecture seule conditionnellement

Comment puis-je faire en sorte que les membres de la classe C puissent être modifiés lorsqu'ils sont référencés de la classe A mais pas modifiés lorsqu'ils sont référencés de la classe B?

IE, ce qui suit devrait être possible;

classA myClassA = new classA(); 
myClassA.myClassC.IssueNumber = 3; 

Mais cela ne devrait pas être possible;

classB myClassB = new classB(); 
myClassB.myClassC.IssueNumber = 3; 

Faire classB.classC lecture seule permet encore de propriétés classC à modifier. Je suis sûr que c'est un truc de base mais je ne trouve pas de réponse simple.

Merci, A

+1

Vous avez probablement ne pas vraiment voulez/besoin de cela. Pouvez-vous fournir un exemple plus précis à clarifier (c'est-à-dire utiliser des classes spécifiques)? –

Répondre

17

Motif 1: Faire une simple interface de lecture seule IRead. Faire une interface d'écriture simple IWrite. Faire une interface de lecture-écriture IReadWrite : IRead, IWrite. Mettre en œuvre classC : IReadWrite. Déclarer myClassA.myClassC comme IReadWrite. Déclarer myClassB.myClassC comme IRead. (Vous n'avez pas à l'utilisateur IWrite nulle part si vous ne avez pas besoin :-))

Modèle 2: créer une lecture seule enveloppe pour classC appelé ReadOnlyClassC et l'utiliser dans un classB.

Le modèle 1 est utilisé par les flux d'E/S pour diviser les implémentations de lecteur et d'écriture, puis les combiner dans des flux de lecture-écriture.

Le modèle 2 est utilisé par les collections génériques pour fournir une facette en lecture seule.

+2

+1 pour le motif 1 – chriszero

+0

c'est bon. – bernhof

+1

+1 pour indiquer où les motifs sont utilisés dans la BCL. – OregonGhost

3

Vous ne pouvez pas le faire en C# comme vous le feriez en C++. Mais vous pouvez définir une interface en lecture seule pour la classe C qui sera gérée par B alors que A gérera le C. réel

2

Vous ne pouvez pas affecter des droits en tant que tels à des classes spécifiques. Cependant, vous pouvez placer la classe A et la classe C dans le même assemblage et la classe B dans une autre. Définissez ensuite l'accesseur set pour la propriété en tant que internal. Cela signifie qu'il ne peut être réglé par les classes dans le même ensemble:

public int IssueNumber 
{ 
    get; 
    internal set; 
} 

Sinon, vous pouvez mettre en œuvre une méthode de classe A qui fixe la valeur de la propriété, mais pas sur la classe B:

public void SetIssueNumber(int value) 
{ 
    this.myClassA.IssueNumber = value; 
} 
3

Je vous suggère de diviser la classe C 2 classes:

class C 
{ 
    protected int _IssueNumber; 

    public int GetIssueNumber() 
    { 
     return _IssueNumber; 
    } 
} 

class WritableC : C 
{ 
    public void SetIssueNumber(int issueNumber) 
    { 
     _IssueNumber = issueNumber; 
    } 
} 

class A 
{ 
    public WritableC myClassC; 
    ... 
} 

class B 
{ 
    public C myClassC; 
    ... 
} 

EDIT:

Comme Martinho Fernandes dit que vous pouvez également utiliser une classe avec 2 interfaces différentes:

interface IC 
{ 
    int IssueNumber { get; } 
} 

interface IWritableC : IC 
{ 
    int IssueNumber { get; set; } 
} 

class C : IWritableC 
{ 
    protected int _IssueNumber; 

    public IssueNumber 
    { 
     get { return _IssueNumber; } 
     set { _IssueNumber = value; } 
    } 
} 

class A 
{ 
    public IWritableC myClassC; 
    ... 
} 

class B 
{ 
    public IC myClassC; 
    ... 
} 
+2

Une autre option consiste à conserver une seule classe C, mais avec une interface implémentée explicitement qui expose le setter. –

1

avoir un booléen isReadOnly dans ClassC.Définissez ce booléen à l'aide d'un constructeur. Lors de la création de l'instance de ClassC dans l'appel ClassB ClassC myClassC = new ClassC(true); Dans le bloc set de IssueNumber, vérifiez la valeur booléenne. Si cela est vrai modifier la valeur

bool isReadOnly; 
public ClassC(bool isReadOnly) 
{ 
    this.isReadOnly = isReadOnly; 
} 

int _issueNumber; 
public int IssueNumber 
{ 
    get 
    { 
     return _issueNumber; 
    } 
    set 
    { 
     if(!isReadOnly) 
     { 
      _issueNumber = value; 
     } 
    } 
} 
1

S'il est si important de faire cette différence, faire une interface:

// read only interface 
interface IC 
{ 
    int IssueNumber { get; } 
} 

class C : IC 
{ 
    int IssueNumber { get; set; } 
} 

// get the full type from A 
class A 
{ 
    C MyClassC { get; } 
} 

// only get read only interface from B 
class B 
{ 
    IC MyClassC { get; } 
} 
Questions connexes