It is a simple issue, where you can subscribe to PropertyChange notifications and detect whenever interested property changes in Object1, set AnotherProperty's value in Another Object. And vice versa. To avoid recursive infinite loop situation, you can keep a flag which tracks direction of change and avoids this infinite loop.
But I wanted to solve this by keeping following constratints
1. I need to reuse this syncing logic wherever required in future.
2. Loosely Coupled.
3. No reflection, I want compile time support to detect any errors or most of them.
4. Should support FluentAPI for better usability.
Few assumption I made are
4. Both objects implements INotifyPropertyChanged event which raises event change notifications whenever property is changed.
Before discussing code, once developed you can use it like following to keep both objects in Sync.
//ViewModel which has a property
Class1 orgViewModel = new Class1();
//Another ViewModel which has another property.
Class2 anotherViewModel = new Class2();
//Sync API will be exposed by this SyncClass Which takes ViewModel types and property type.
SyncClass
//Configure ViewModel with predicate to detect when property is changed and provide functions to read and write property values.
SyncClass.MonitorClass(orgViewModel, (propname) => { return propname == "MyVal"; })
.SetGetValue(()=>orgViewModel.MyVal)
.SetSetValue((i)=>orgViewModel.MyVal=i);
//Configure another ViewModel with predicate to detect when property is changed and provide functions to read and write property values.
SyncClass.MonitorAnotherClass(anotherViewModel, (propname) => { return propname == "AnotherVal"; })
.SetGetValue(()=>anotherViewModel.AnotherVal)
.SetSetValue((i1)=>anotherViewModel.AnotherVal=i1);
//Start Synchronization.
SyncClass.StartSync();
Once you configure you view models and property in above manner SynClass will auto sync two properties.
Code Listing
delegate void ValueChanged(object sender,EventArgs e);
class UsingClassbool IsOriginator = false;
{
public event ValueChanged ObjectValueChanged;
T _MonitorObject;
Func_GetValue; Action
_SetValue; Func<string,bool> _IsPropChanged;
public UsingClass(T MonitorObject,Func<string,bool> IsPropertyChanged)
{
_IsPropChanged = IsPropertyChanged;
_MonitorObject = MonitorObject;
INotifyPropertyChanged propChanged = _MonitorObject as INotifyPropertyChanged;
if (propChanged != null)
{
propChanged.PropertyChanged += (o1, e1) =>
{
if (_IsPropChanged(e1.Proeprtyname))
{
this.IsOriginator = true;
if (this.ObjectValueChanged != null)
{
this.ObjectValueChanged(this, new EventArgs());
}
}
};
}
}
public UsingClassSetGetValue( FuncGetValue) return this;
{
_GetValue=GetValue;
}
public T1 GetValue()
{
return _GetValue();
}
public void SetSetValue(ActionSetValue) this._SetValue = SetValue;
{
}
public void SetValue(T1 val1)
{
if (!IsOriginator)
{
_SetValue(val1);
}
else
{
IsOriginator = false;
}
}
}
class SyncClassUsingClass
{
Object1; UsingClass
Object2; public UsingClass
MonitorClass(T MonitorObject, Func<string,bool> CheckPropertyChanged)
{
Object1 = new UsingClass(MonitorObject,CheckPropertyChanged); return Object1;
}
public UsingClassMonitorAnotherClass(T1 MonitorAnotherObject, Func<string, bool> CheckPropertyChanged)
{
Object2 = new UsingClass(MonitorAnotherObject, CheckPropertyChanged); return Object2;
}
public void StartSync()
{
Object1.ObjectValueChanged += (o, e) =>
{
Object2.SetValue(Object1.GetValue());
};
Object2.ObjectValueChanged += (o1, e1) =>
{
Object1.SetValue(Object2.GetValue());
};
}
}
I prepared a sample in Console Application which will be easy to execute and see how its working.
Click here to download sample application. You need VS 2010 to open this solution.
Hope you enjoyed this code crunch..