Atribuir propriedade com um ExpressionTree
Estou brincando com a idéia de passar uma atribuição de propriedade para um método como uma árvore de expressão. O método Invocaria a expressão para que a propriedade fosse atribuída corretamente e farejaria o nome da propriedade que acabou de ser atribuída para que eu possa aumentar o evento PropertyChanged. A idéia é que eu gostaria de poder usar propriedades automáticas finas em meus WPF ViewModels e ainda ter o evento PropertyChanged disparado.
Sou um ignorante no ExpressionTrees, então espero que alguém possa me indicar a direção certa:
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);
}
}
O problema é que não sei ao certo como chamar isso. Essa tentativa ingênua foi rejeitada pelo compilador por razões que, com certeza, serão óbvias para quem puder responder a isso:
ViewModelBase vm = new ViewModelBase();
vm.RunAndRaise(() => vm.Value = 1);
EDITA
Obrigado @sick pela resposta perfeita. Mudei uma coisinha e transformei-a em um método de extensão. Aqui está o exemplo de código completo com teste de unidade:
[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);
}
}