2010-08-05 8 views
2

J'ai un cas d'utilisation que je n'ai jamais vraiment traité auparavant. J'ai un objet qui après que l'utilisateur clique sur "Enregistrer" ne devrait pas être changé. Initialement j'ai créé deux objets, DraftObject et SavedObject. Pour ce dernier, j'ai créé un constructeur qui n'acceptait que DraftObject et définissait chaque propriété comme un ensemble protégé.Empêche la modification d'un objet après son entrée dans un certain état? (C#)

Cela fonctionne mais ne semble pas idéal. Il semble que je devrais être en mesure de définir une propriété sur mon objet qui contrôle si les autres champs sont modifiables. Quelle est la meilleure façon de faire cela? Pardonnez mon pseudo-code, mais ce que je caressait:

public class MySpecialObject { 
     public virtual string MyProperty { get { return MyProperty; } 
      set { 
       if (State == "Locked") 
       { 
        return; 
       } else 
       { 
        MyProperty = MyProperty; 
       } 
      } 
     public virtual string State { get { return State; } 
      set { 
       if (State == "Locked") 
       { 
        return; 
       } else 
       { 
        State = State; 
       } 
      } 

Cela semble laid, surtout si je dois le faire pour chaque propriété unique dans ma classe. Il doit y avoir une meilleure façon de faire cela, des idées?

+4

votre approche semble OK pour moi; C'est ce que 'SecureString' fait avec la méthode' MakeReadOnly' http://msdn.microsoft.com/en-us/library/system.security.securestring.makereadonly.aspx. Cela déclenche une exception 'InvalidOperationException' si un appelant tente de modifier la chaîne après l'appel de 'MakeReadOnly'. – JLWarlow

Répondre

2

C'est en fait un problème assez intéressant, car il y a beaucoup à dire pour les objets qui sont soit immuables, soit qui commencent à être mutables mais peuvent être verrouillés pour devenir immuables.

En répondant à votre question en particulier, je pense qu'il peut être plus logique de lancer un InvalidOperationException s'il y a une tentative de définir une propriété verrouillée. Je ne connais aucun nettoyeur ou meilleur moyen.

modifier

Dans un poste parallèle, JLWarlow a souligné que c'est exactement comment fonctionne SecureString lorsque vous appelez MakeReadOnly.

1

Si sa seule fonction ou deux pour l'amour de la simplicité ne juste comme vous écrit si vous le faites souvent, il peut être un bon endroit pour utiliser AOP

http://en.wikipedia.org/wiki/Aspect-oriented_programming

Vous pouvez ensuite écrire un aspect Cela empêche les modifications lorsque l'élément est dans un certain état. Une autre option qui est presque aussi verbeuse que votre code, mais qui peut être un peu plus agréable, est d'utiliser le modèle de conception d'état, où vous avez une classe abstraite avec différentes implémentations par état, donc la classe d'état verrouillée ne permet pas Les changements

http://en.wikipedia.org/wiki/State_pattern

+0

Cet article répertorie près d'une douzaine de cadres orientés aspect différents pour .NET. Quelqu'un en particulier que vous recommanderiez? –

+0

Spring.Net a une grande base d'utilisateurs et est basé sur le framework Java Spring Voici un article qui compare les cadres http://www.codeproject.com/KB/cs/AOP_Frameworks_Rating.aspx – Sruly

+0

article intéressant, bien qu'il On dirait qu'il favorise PostSharp sur Spring.Net. De toute façon, +1 pour la recherche pertinente et de bonnes idées. –

0

Je sais que votre échantillon est pseudo-code, mais peut-être vous pouvez utiliser une propriété booléenne IsLocked et écrire plus simple:

set { 
      _MyProperty = IsLocked? _MyProperty:value;  
    } 
+0

Plus simple ici, plus compliqué ailleurs.Le setter de 'State' devrait vérifier que' value' est '' Locked'' et ensuite 'IsLocked'. Pourtant, il pourrait être un peu plus rapide pour les autres accessoires. –

+0

'IsLocked' peut lui-même être un getter de propriété. –

+0

@Ben: Eh bien, je pense que cela pourrait fonctionner mieux comme une méthode, un peu comme 'SecureString.MakeReadOnly'. Je dis cela parce qu'il ne serait jamais possible de mettre 'IsLocked' à' false'. Il peut toujours être utile d'avoir un accessoire 'IsReadOnly' qui est lui-même en lecture seule. Dans tous les cas, l'OP est sur le verrouillage basé sur un état, pas un verrou explicite. –