.net propertychange 通知处理程序 - 字符串与字符串表达式
-
12-09-2019 - |
题
使用 WPF 让我成为了 INotifyPropertyChanged 的粉丝。我喜欢使用一个助手,它接受一个表达式并将名称作为字符串返回(请参见下面的示例代码)。然而,在我看到的许多非常熟练的程序员的应用程序中,我看到了处理原始字符串的代码(参见下面的第二个示例)。我所说的精通是指知道如何使用表达式的 MVP 类型。
对我来说,除了简单的重构之外,让编译器捕获错误的机会使得表达式方法更好。是否存在我所缺少的支持使用原始字符串的论点?
欢呼,贝里尔
表达式助手示例:
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);
}
原始字符串示例代码(在某些 ViewModelBase 类型类中):
/// <summary>
/// Warns the developer if this object does not have
/// a public property with the specified name. This
/// method does not exist in a Release build.
/// </summary>
[Conditional("DEBUG"), DebuggerStepThrough]
public void VerifyPropertyName(string propertyName) {
// Verify that the property name matches a real,
// public, instance property on this object.
if (TypeDescriptor.GetProperties(this)[propertyName] == null) {
string msg = "Invalid property name: " + propertyName;
if (ThrowOnInvalidPropertyName) throw new Exception(msg);
else Debug.Fail(msg);
}
}
/// <summary>
/// Returns whether an exception is thrown, or if a Debug.Fail() is used
/// when an invalid property name is passed to the VerifyPropertyName method.
/// The default value is false, but subclasses used by unit tests might
/// override this property's getter to return true.
/// </summary>
protected virtual bool ThrowOnInvalidPropertyName { get; private set; }
解决方案 3
我结束了花费更多的时间在这方面比我预期的,但确实发现有安全/ refactorability和性能的一个很好的搭配的解决方案。好的背景读数,并使用反射一个替代的解决方案是此处。我喜欢萨沙理发的解决方案更好(背景这里
我们的想法是使用表达式帮手将参与变更通知,但只取命中一次它,通过存储在你的视图模型所得PropertyChangedEventArgs一个属性。例如:
private static PropertyChangedEventArgs mobilePhoneNumberChangeArgs =
ObservableHelper.CreateArgs<CustomerModel>(x => x.MobilePhoneNumber);
HTH,结果 Berryl
其他提示
对我来说,机会对于具有赶上编译器的错误,除了容易的重构,使Exression办法更好。是否有一个有利于参数采用的原串的,我的失踪?
我同意,而且就个人而言,使用的表达方法,在我自己的代码,在大多数情况下。
然而,有两个原因,我知道的,以避免这样的:
这是不太明显,特别是小的经验。网的开发。写作
RaisePropertyChanged(() => this.MyProperty );
并不总是显而易见的人RaisePropertyChanged("MyProperty");
, 和不匹配框架样本,等等。还有一些性能的开销使用的表达。就个人而言我不觉得这是真正有意义的一个原因,因为这是通常使用的数据结合方案(它已经缓慢,由于反射的使用),但这可能是一个有效的担忧。
使用 TypeDescriptor
方法的好处是,它使基于ICustomTypeDescriptor实现其中实现能够有效地对飞用于正在描述的类型创建动态属性元数据的动态特性的情况。考虑一个数据集,其“属性”是由结果确定设置它被填充有例如。
这是什么,因为它是基于相对于字符串的实际类型信息(一件好事)表达式不提供但
堆栈遍历是缓慢和λ表达是更慢。我们有类似于众所周知的lambda表达式,但几乎一样快,字符串文字的解决方案。看到 http://zamboch.blogspot.com/2011 /03/raising-property-changed-fast-and-safe.html
.NET 4.5中引入了CallermemberName属性,此属性只能连接到可选的字符串参数,并且如果呼叫者在函数调用中未使用该参数,则呼叫者的名称将在字符串参数中传递
这消除了在引发 PropertyChanged 事件时指定属性名称的需要,因此它可以与重构一起使用,并且因为更改是在编译时完成的,所以性能没有差异。
下面是一个实施示例,更多信息可以在以下位置找到: http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.callermembernameattribute.aspx 和 http://msdn.microsoft.com/en-us/library/hh534540.aspx
public class DemoCustomer : INotifyPropertyChanged
{
string _customerName
public string CustomerName
{
get { return _customerNameValue;}
set
{
if (value != _customerNameValue)
{
_customerNameValue = value;
NotifyPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}