2012-05-05 52 views
0

我已经看到了这样做的各种方法,包括反射,组件模型类型描述符,表达式树和方面,但我仍不确定下面的代码是否使用.Net实现了以下所有目标4.0或更高版本:获取PropertyInfo名称和值

  1. 类型安全,重构友好(没有魔法字符串),并通过多次调用
  2. 可读
  3. 最大限度地提高性能提供一个属性
  4. 的名称提供的属性值

代码如何改进?

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 
} 

回答

1

可能通过编译表达式树并将其缓存以供将来使用,而不是每次调用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>>(); 
} 

注意我已经使用了泛型静态类型来保存缓存字典实例。这是为每种不同的属性类型有效创建单独的类型化缓存的简便方法。

0

这是一个很长的故事,我想现在还没有比其他人更好的方法。我认为表达式在大多数通常的业务场景中不会产生性能瓶颈(如果需要,可以优化一小段需要更快通知的代码),所以这种方法应该没问题。

请记住,创建表达式树要花费更多的时间来解析它,所以请确保您只做一次(即使用静态类级表达式变量)。但是,在这种情况下,您的模型代码会变得有点臃肿。

我个人更喜欢使用基于字符串的INPC处理。 ReSharper在重构时可以很好地与字符串一起工作,所以我可以称它比较安全。据我所知,这是最快的方法。使用VS或ReSharper片段,您可以轻松地在几个按键中编写属性。

关于属性值 - 它不用于既不INotifyPropertyChanging也不由INotifyPropertyChanged的接口。你为什么需要它?

+0

用于IsDirty检查;如果该值不同于缓存值快照,则比我的对象IsDirty。干杯 – Berryl