Reputation: 49978
I’m trying to manage multiple models in a messaging based system. Each model might have values that are dependent on other models. For example:
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);
}
}
I would also like to use the MVC pattern, but instead of passing a Model instance, I thought I would pass in a ‘Repository’ instance. The ‘Repository’ instance would act as a manager for handling all the Model instances. The result would look something like this:
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;
}
}
In this situation, if V1Model’s property changed, in V1ModelPropertyChanged, I would know the dependency on V2Model’s object, and update it with the appropriate values. Is there a better way of handling this interdependent model scheme, or would this be an acceptable solution? I am not really looking for anything 3rd party.
Upvotes: 1
Views: 599
Reputation: 1116
Maybe I'm missing something, but isn't this what the observer pattern is for? If you set up the models as observers of each other (i.e., with delegates or events), then the controller should be able to remain blissfully ignorant of the dependencies.
Upvotes: 1
Reputation: 921
If you want to handle this elegantly, you're going to need to have some component track the dependencies between the models. When a property changes, you would iterate over all of the dependencies for that property and then update them appropriately.
Perhaps your BaseRepository
might hold a reference to a DependencyManager
class. That class would have to have a list of all properties which depend on one another.
A simple implementation might look like this:
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;
}
}
}
}
Then when you detect a property change, you can query the DependencyManager for what else needs to change. But be careful to check for circular dependencies when you cascade!
Upvotes: 1