This question will probably take a while to explain, and I'll need to provide background...
This is just something I'm playing about with and isn't for production, but at the moment I have some code which looks like this:
var myDataModel = new DataModel();
myDataModel.PropertyChanged += myDataModel_PropertyChanged;
myDataModel.ChangeProperty(t => t.TestValue, 2);
So, rather than using myDataModel.TestValue = 2
directly, I'm using a ChangeProperty
extension method so that I can handle all of the change events and do anything I want to in one place. My extension method looks like this (and yes, I know it's hacky):
public static class NotifyPropertyChangedExtensions
{
public static void ChangeProperty<T, U>(
this T instance,
Expression<Func<T, U>> propertyToChange,
U newValue)
{
var member = propertyToChange.Body as MemberExpression;
if (member != null)
{
if (!propertyToChange.Compile().Invoke(instance).Equals(newValue))
{
var setProperty = instance.GetType().GetProperty(
member.Member.Name,
BindingFlags.SetProperty |
BindingFlags.Public |
BindingFlags.Instance);
if (setProperty != null)
{
// actually set the property
setProperty.SetValue(instance, newValue, null);
// raise the property changed event
if (typeof(INotifyPropertyChanged).IsAssignableFrom(
typeof(T)))
{
var delegatesToCall =
instance.GetType().GetField("PropertyChanged",
BindingFlags.Instance |
BindingFlags.NonPublic)
.GetValue(instance) as MulticastDelegate;
if (delegatesToCall != null)
{
var eventArgs = new PropertyChangedEventArgs(
setProperty.Name);
foreach (var @delegate in
delegatesToCall.GetInvocationList())
{
@delegate.Method.Invoke(
@delegate.Target,
new object[] { instance, eventArgs });
}
}
}
}
}
}
else
{
throw new ArgumentException(
string.Format(
"Cannot determine the property to change {0}",
propertyToChange));
}
}
}
With this architecture, my data model is quite clean:
public class DataModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public int TestValue { get; set; }
}
That is, I can use auto-properties, and don't need to worry about raising events etc.
Now, what I actually want to do is something closer to this:
var dataModel = new DataModel();
myDataModel.PropertyChanged += myDataModel_PropertyChanged;
myDataModel.TestValue.Set(2); // this is what I want...
So, I'm thinking I'll basically need an extension method - but I can only see how to send the property itself (the TestValue in this case), and the new value. So then I wondered if it's possible, given a property, to find out the instance of the class it belongs to?