0

我已经看到了执行此操作的各种方法,包括反射、组件模型类型描述符、表达式树和方面,但我仍然不确定下面的代码是否使用 .Net 4.0 或更高版本实现了以下所有目标:

  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
}
4

2 回答 2

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>>();
}

请注意,我使用了一个通用静态类型来保存缓存字典实例。这是为每种不同的属性类型有效地创建单独的类型化缓存的便捷方法。

于 2012-05-05T17:25:30.733 回答
0

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

请记住,创建表达式树比解析它更耗时,因此请确保您只执行一次(即使用静态类级表达式变量)。但是,在这种情况下,您的模型代码会变得有点臃肿。

我个人更喜欢使用基于字符串的 INPC 处理。在重构方面,ReSharper 可以很好地处理字符串,因此我可以称它为相对安全的。据我所知,这是最快的方法。并且使用 VS 或 ReSharper 代码段,您可以轻松地通过几次击键来编写您的属性。

关于属性值 - INotifyPropertyChangingINotifyPropertyChanged接口都没有使用它。你为什么需要它?

于 2012-05-05T12:54:29.530 回答