我已經看到了各種方法,包括反射,組件模型類型描述符,表達式樹和方面,但我仍然不確定下面的代碼是否使用.Net 4.0或更高版本實現了以下所有目標:
如何改進代碼?
protected void NotifyOfPropertyChanging<TProperty>(Expression<Func<TProperty>> property) {
var memberExpression = (MemberExpression)property.Body;
var prop = (PropertyInfo) memberExpression.Member;
var propertyName = prop.Name;
var value = prop.GetValue(this, null);
// fire INPC using propertyName
// use value and name to do IsDirty checking
}
您可以通過編譯表達式樹並將其緩存以備將來使用而不是每次都調用GetValue
來提高性能。但是,只有在當前實現導致瓶頸時才應進行此類優化。
void NotifyOfPropertyChanging<TProperty>(Expression<Func<TProperty>> property)
{
var memberExpression = (MemberExpression) property.Body;
var prop = (PropertyInfo) memberExpression.Member;
Func<TProperty> accessor;
if (!TypedAccessorCache<TProperty>.Cache.TryGetValue(prop, out accessor))
{
accessor = property.Compile();
TypedAccessorCache<TProperty>.Cache[prop] = accessor;
}
var value = accessor();
// ...
}
static class TypedAccessorCache<TProperty>
{
public static readonly IDictionary<PropertyInfo, Func<TProperty>> Cache =
new Dictionary<PropertyInfo, Func<TProperty>>();
}
注意我使用了通用的靜態類型來保存緩存字典實例。這是為每種不同屬性類型有效創建單獨類型緩存的便捷方法。
這是一個很長的故事,我想仍然沒有一種方法比其他方法更好。我認為這些表達式在大多數通常的業務場景中都不會成為性能瓶頸(如果你需要的話,你可以優化一小段需要更快通知的代碼),所以這種方法應該沒問題。
請記住,創建表達式樹比解析它要花費更多時間,因此請確保只執行一次(即使用靜態類級表達式變量)。但是,在這種情況下,您的模型代碼會變得有點臃腫。
我個人更喜歡使用基於字符串的INPC處理。在重構時,ReSharper可以很好地處理字符串,所以我可以稱之為相對安全。據我所知,這是最快的方法。使用VS或ReSharper片段,您可以輕鬆地在幾次擊鍵中編寫屬性。
關於屬性值 - INotifyPropertyChanging和INotifyPropertyChanged接口既不使用它也不使用它。你為什麼需要它?