Я играю с идеей передачи присвоения свойства методу в качестве дерева выражений. Этот метод будет вызывать выражение так, чтобы свойство было назначено правильно, а затем вынюхило имя свойства, которое было только что назначено, поэтому я могу поднять событие PropertyChanged. Идея состоит в том, что я хотел бы иметь возможность использовать тонкие авто-свойства в моих WPF ViewModels и все еще иметь событие PropertyChanged.
Я - невежда с ExpressionTrees, поэтому я надеюсь, что кто-то может указать мне в правильном направлении:
public class ViewModelBase {
public event Action<string> PropertyChanged = delegate { };
public int Value { get; set; }
public void RunAndRaise(MemberAssignment Exp) {
Expression.Invoke(Exp.Expression);
PropertyChanged(Exp.Member.Name);
}
}
Проблема в том, что я не уверен, как это назвать. Эта наивная попытка была отвергнута компилятором по причинам, которые, я уверен, будут очевидны для всех, кто может ответить на этот вопрос:
ViewModelBase vm = new ViewModelBase();
vm.RunAndRaise(() => vm.Value = 1);
ИЗМЕНИТЬ
Спасибо @svick за отличный ответ. Я переместил одну маленькую вещь и превратил ее в метод расширения. Здесь полный образец кода с unit test:
[TestClass]
public class UnitTest1 {
[TestMethod]
public void TestMethod1() {
MyViewModel vm = new MyViewModel();
bool ValuePropertyRaised = false;
vm.PropertyChanged += (s, e) => ValuePropertyRaised = e.PropertyName == "Value";
vm.SetValue(v => v.Value, 1);
Assert.AreEqual(1, vm.Value);
Assert.IsTrue(ValuePropertyRaised);
}
}
public class ViewModelBase : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged = delegate { };
public void OnPropertyChanged(string propertyName) {
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public class MyViewModel : ViewModelBase {
public int Value { get; set; }
}
public static class ViewModelBaseExtension {
public static void SetValue<TViewModel, TProperty>(this TViewModel vm, Expression<Func<TViewModel, TProperty>> exp, TProperty value) where TViewModel : ViewModelBase {
var propertyInfo = (PropertyInfo)((MemberExpression)exp.Body).Member;
propertyInfo.SetValue(vm, value, null);
vm.OnPropertyChanged(propertyInfo.Name);
}
}