2010-11-01 59 views
1

我正试图在基于消息传递的系统中管理多个模型。每个模型可能具有依赖于其他模型的值。例如:管理多个相互依赖的模型

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); 
     } 
    } 

我也想用MVC模式,但不是通过模型实例,我想我会通过在一个“库”的实例。 'Repository'实例将充当处理所有Model实例的管理器。其结果将是这个样子:

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; 
     } 
    } 

在这种情况下,如果V1Model的性质变了,V1ModelPropertyChanged,我就知道V2Model的对象上的依赖,并用适当的值更新。处理这种相互依存的模型方案有没有更好的方法,或者这是一个可接受的解决方案?我没有真正寻找任何第三方。

+0

它是web还是WPF/SL? – Aliostad 2010-11-01 14:19:43

+0

它是Winforms。 – SwDevMan81 2010-11-05 15:29:57

+2

K.I.S.S.发生了什么事作为设计模式?你能否抽象地解释你想要在没有代码的情况下实现什么?也许有一个比你刚开始的解决方案更简单的解决方案。 – 2010-11-06 19:11:34

回答

1

如果你想处理这个优雅,你将需要有一些组件跟踪模型之间的依赖关系。当一个属性发生变化时,您将遍历该属性的所有依赖关系,然后适当地更新它们。

也许你的BaseRepository可能会引用DependencyManager类。该班级必须列出所有相互依赖的房产。

一个简单的实现可能是这样的:

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; 
      } 
     } 
    } 
} 

然后,当你发现一个属性的变化,你可以查询DependencyManager的还有什么需要改变。但是在级联时要小心检查循环依赖关系!

+0

感谢您的建议,这绝对是一个可能的解决方案。 – SwDevMan81 2010-11-09 20:32:25

1

也许我错过了一些东西,但是这不是observer pattern的用途吗?如果您将模型设置为彼此的观察者(即使用委托或事件),那么控制器应该能够保持对相关性的无知。

+0

+1,除非我也失去了一些东西......虽然我觉得在.NET中使用事件/代表会更优雅。 – Crisfole 2010-11-10 17:55:58

+0

这意味着每个模型都会收到关于每个PropertyChanged事件的通知,即使他们不关心它。想象一下在model1中属性发生变化的场景,该变化会通知所有模型有关该变化,这会更改model2中的值。模型2中的这种改变会通知所有模型,并且继续。它不是最直接的方式。我正在寻找一个解决方案,说,嘿这个属性刚刚改变,这个其他模型有一个值,根据该值计算,去更新它。 – SwDevMan81 2010-11-10 18:15:34

+0

一般而言,您需要这种行为,以便随着模型的发展,他们可以决定他们关心的信息,而无需改变其他模型或控制器。添加一个新的依赖字段/属性然后意味着你只更改一个模型/类而不是两个(你正在更新的模型加上它所依赖的模型),甚至三个(你正在更新的模型,它依赖的模型和控制器)。 – 2010-11-10 21:35:01