2010-11-01 15 views
1

J'essaie de gérer plusieurs modèles dans un système basé sur la messagerie. Chaque modèle peut avoir des valeurs dépendantes d'autres modèles. Par exemple:Gestion de plusieurs modèles interdépendants

public class V2Model : BaseModel 
    { 
     private int mSomeVal; 
     private byte mSomeByte; 

     // … 

     // Update mSomeByte based on multiple models values 
     public void SetMultipleDependecyValue(int someIntFromModel1, short someShawteeyFromModel3) 
     { 
     mSomeByte = Convert.ToByte((someShawteeyFromModel3/someIntFromModel1) + mSomeVal); 
     } 
    } 

Je voudrais également utiliser le modèle MVC, mais au lieu de passer une instance de modèle, je pensais que je passerais dans une instance « dépôt ». L'instance 'Repository' agirait comme un gestionnaire pour gérer toutes les instances du modèle. Le résultat ressemblerait à quelque chose comme ceci:

public class V1Controller<ViewType, ModelType> 
     where ViewType : IV1View 
     where ModelType : BaseModel 
    { 
     ViewType mView; 
     BaseRepository mBaseRep; 

     public V1Controller(ViewType view, BaseRepository rep) 
     { 
     mView = view; 
     mBaseRep = rep; 
     mBaseRep.GetModel<ModelType>().PropertyChanged += new PropertyChangedEventHandler(V1ModelPropertyChanged); 
     } 

     void V1ModelPropertyChanged(object sender, PropertyChangedEventArgs e) 
     { 
     switch (e.PropertyName) 
     { 
      case "SomeVal": 
       // Update the view 
       int some_val = mBaseRep.GetModel<ModelType>().SomeVal; 
       mView.HexSomeValue = some_val; 
       // Oh BTW, we know V2Model's value depends on this... update it with V1Model and V3Model's values 
       short some_short = mBaseRep.GetModel<V3Model>().SomeShawteey; 
       mBaseRep.GetModel<V2Model>().SetMultipleDependecyValue(some_val, some_short); 
       break; 
     } 
     } 

     public void UpdateVal(int someValue) 
     { 
     mBaseRep.GetModel<ModelType>().SomeVal = someValue; 
     } 
    } 

Dans cette situation, si la propriété de V1Model a changé, en V1ModelPropertyChanged, je sais la dépendance sur l'objet de V2Model, et le mettre à jour avec les valeurs appropriées. Y a-t-il une meilleure façon de gérer ce modèle de modèle interdépendant, ou serait-ce une solution acceptable? Je ne cherche pas vraiment de tiers.

+0

S'agit-il de Web ou de WPF/SL? – Aliostad

+0

C'est Winforms. – SwDevMan81

+2

Qu'est-il arrivé à K.I.S.S. comme un motif de conception? Pouvez-vous expliquer de façon abstraite ce que vous essayez d'atteindre sans code. Peut-être qu'il existe une solution plus simple que celle avec laquelle vous avez commencé. –

Répondre

1

Si vous voulez gérer cela élégamment, vous aurez besoin d'avoir un certain composant pour suivre les dépendances entre les modèles. Lorsqu'une propriété est modifiée, vous devez parcourir toutes les dépendances de cette propriété, puis les mettre à jour de manière appropriée.

Peut-être que votre BaseRepository pourrait contenir une référence à une classe DependencyManager. Cette classe devrait avoir une liste de toutes les propriétés qui dépendent les unes des autres.

Une implémentation simple pourrait ressembler à ceci:

class PropertyDescriptor 
{ 
    public Type ModelType { get; set; } 
    public string Property { get; set; } 
} 

class DependencyManager 
{ 
    private Dictionary<PropertyDescriptor, List<PropertyDescriptor>> _dependencies = new Dictionary<PropertyDescriptor, List<PropertyDescriptor>>(); 

    public void RegisterDependency(PropertyDescriptor property, PropertyDescriptor dependentProperty) 
    { 
     if (!_dependencies.ContainsKey(property)) 
     { 
      _dependencies.Add(property, new List<PropertyDescriptor>()); 
     } 
     _dependencies[property].Add(dependentProperty); 
    } 

    public IEnumerable<PropertyDescriptor> GetDependentProperties(PropertyDescriptor property) 
    { 
     if (!_dependencies.ContainsKey(property)) 
     { 
      yield break; 
     } 
     else 
     { 
      foreach (PropertyDescriptor p in _dependencies[property]) 
      { 
       yield return p; 
      } 
     } 
    } 
} 

Puis, quand vous détectez un changement de propriété, vous pouvez interroger le DependencyManager pour ce qu'il reste à changer. Mais attention à vérifier les dépendances circulaires lorsque vous cascadez!

+0

Merci pour la suggestion, c'est certainement une solution possible. – SwDevMan81

1

Peut-être qu'il me manque quelque chose, mais n'est-ce pas ce à quoi sert le observer pattern? Si vous configurez les modèles en tant qu'observateurs les uns des autres (c'est-à-dire avec des délégués ou des événements), le contrôleur doit pouvoir rester parfaitement ignorant des dépendances.

+0

+1 à moins que je manque quelque chose aussi ... bien que je me sente comme. NET en utilisant des événements/délégués serait plus élégant. – Crisfole

+0

Cela signifie que chaque modèle est averti de chaque événement PropertyChanged, même si cela ne le concerne pas. Imaginez le scénario où une propriété change dans model1, cette modification notifie tous les modèles de la modification, ce qui modifie une valeur dans model2. Ce changement dans model2 notifie alors tous les modèles, et ainsi de suite. Ce n'est pas la manière la plus directe. Je cherche une solution qui dit, hé cette propriété vient de changer, cet autre modèle a une valeur qui est calculée en fonction de cette valeur, allez la mettre à jour. – SwDevMan81

+0

Généralement, vous voulez ce comportement, afin que vos modèles puissent évoluer avec le temps et décider des informations qui les intéressent sans que les autres modèles ou contrôleurs ne changent. L'ajout d'un nouveau champ/propriété dépendant signifie que vous changez seulement un modèle/classe au lieu de deux (le modèle que vous mettez à jour plus le modèle dont il dépend) ou même trois (le modèle que vous mettez à jour, le modèle et le controlle). –