Wpf .net propertychange通知处理程序-字符串与表达式
使用WPF使我成为INotifyPropertyChanged的粉丝。我喜欢使用一个helper,它接受一个表达式并以字符串形式返回名称(参见下面的示例代码)。然而,在我看到的很多应用程序中,我都是非常熟练的程序员,我看到了处理原始字符串的代码(参见下面的第二个示例)。所谓熟练,我指的是懂得如何使用表达式的MVP类型 对我来说,除了简单的重构之外,让编译器捕捉错误的机会使EXPRESSION方法变得更好。是否有支持使用我缺少的原始字符串的论点 干杯, 贝里尔 表达式帮助器示例:Wpf .net propertychange通知处理程序-字符串与表达式,wpf,expression,inotifypropertychanged,Wpf,Expression,Inotifypropertychanged,使用WPF使我成为INotifyPropertyChanged的粉丝。我喜欢使用一个helper,它接受一个表达式并以字符串形式返回名称(参见下面的示例代码)。然而,在我看到的很多应用程序中,我都是非常熟练的程序员,我看到了处理原始字符串的代码(参见下面的第二个示例)。所谓熟练,我指的是懂得如何使用表达式的MVP类型 对我来说,除了简单的重构之外,让编译器捕捉错误的机会使EXPRESSION方法变得更好。是否有支持使用我缺少的原始字符串的论点 干杯, 贝里尔 表达式帮助器示例: public s
public static string GetPropertyName<T>(Expression<Func<T, object>> propertyExpression)
{
Check.RequireNotNull<object>(propertyExpression, "propertyExpression");
switch (propertyExpression.Body.NodeType)
{
case ExpressionType.MemberAccess:
return (propertyExpression.Body as MemberExpression).Member.Name;
case ExpressionType.Convert:
return ((propertyExpression.Body as UnaryExpression).Operand as MemberExpression).Member.Name;
}
var msg = string.Format("Expression NodeType: '{0}' does not refer to a property and is therefore not supported",
propertyExpression.Body.NodeType);
Check.Require(false, msg);
throw new InvalidOperationException(msg);
}
private static PropertyChangedEventArgs mobilePhoneNumberChangeArgs =
ObservableHelper.CreateArgs<CustomerModel>(x => x.MobilePhoneNumber);
公共静态字符串GetPropertyName(表达式propertyExpression)
{
检查.RequireNotNull(propertyExpression,“propertyExpression”);
开关(propertyExpression.Body.NodeType)
{
case ExpressionType.MemberAccess:
返回(propertyExpression.Body作为MemberExpression).Member.Name;
大小写表达式类型。转换:
返回((propertyExpression.Body作为UnaryExpression)。操作数作为MemberExpression)。Member.Name;
}
var msg=string.Format(“表达式节点类型:{0}”未引用属性,因此不受支持”,
propertyExpression.Body.NodeType);
检查.Require(false,msg);
抛出新的InvalidOperationException(消息);
}
原始字符串示例代码(在某些ViewModelBase类型类中):
//
///如果此对象没有
///具有指定名称的公共属性。这
///方法在发布版本中不存在。
///
[条件(“调试”),调试步骤至]
public void VerifyPropertyName(字符串propertyName){
//验证属性名称是否与实数匹配,
//此对象的公共、实例属性。
if(TypeDescriptor.GetProperties(此)[propertyName]==null){
string msg=“无效的属性名称:”+propertyName;
if(ThrowOnInvalidPropertyName)抛出新异常(msg);
else调试失败(msg);
}
}
///
///返回是否引发异常,或者是否使用了Debug.Fail()
///将无效的属性名称传递给VerifyPropertyName方法时。
///默认值为false,但单元测试使用的子类可能会
///重写此属性的getter以返回true。
///
受保护的虚拟bool ThrowOnInvalidPropertyName{get;private set;}
对我来说,除了简单的重构之外,让编译器捕捉错误的机会使EXPRESSION方法变得更好。是否有支持使用我缺少的原始字符串的论点
我个人同意,在大多数情况下,在我自己的代码中使用表达式方法
但是,我知道有两个原因可以避免这种情况:
RaisePropertyChanged(()=>this.MyProperty)代码>对于人们来说并不总是像RaisePropertyChanged(“MyProperty”)代码>,并且与框架示例不匹配,等等
RaisePropertyChanged(()=>this.MyProperty)代码>对于人们来说并不总是像RaisePropertyChanged(“MyProperty”)代码>,并且与框架示例不匹配,等等
然而,这是表达式没有提供的,因为它基于实际的类型信息(这是一件好事),而不是字符串。我在这方面花费的时间比我预期的要多,但确实找到了一个安全性/可重构性和性能完美结合的解决方案。良好的背景阅读和使用反射的替代解决方案是必要的。我更喜欢Sacha Barber的解决方案(背景) 其思想是为将参与更改通知的属性使用表达式帮助器,但只对其进行一次命中,方法是将生成的PropertyChangedEventArgs存储在视图模型中。例如:
public static string GetPropertyName<T>(Expression<Func<T, object>> propertyExpression)
{
Check.RequireNotNull<object>(propertyExpression, "propertyExpression");
switch (propertyExpression.Body.NodeType)
{
case ExpressionType.MemberAccess:
return (propertyExpression.Body as MemberExpression).Member.Name;
case ExpressionType.Convert:
return ((propertyExpression.Body as UnaryExpression).Operand as MemberExpression).Member.Name;
}
var msg = string.Format("Expression NodeType: '{0}' does not refer to a property and is therefore not supported",
propertyExpression.Body.NodeType);
Check.Require(false, msg);
throw new InvalidOperationException(msg);
}
private static PropertyChangedEventArgs mobilePhoneNumberChangeArgs =
ObservableHelper.CreateArgs<CustomerModel>(x => x.MobilePhoneNumber);
<代码