简体   繁体   English

获取PropertyInfo名称和值

[英]Getting PropertyInfo Name and Value

I have seen various ways of doing this including reflection, component model type descriptors, expression trees, and aspects, BUT I'm still not sure whether the code below achieves all of the following objectives using .Net 4.0 or higher: 我已经看到了各种各样的方法,包括反射,组件模型类型描述符,表达式树和方面,但是我仍然不确定下面的代码是否使用.Net 4.0或更高版本实现了以下所有目标:

  1. Be type safe, refactor friendly (no magic strings), and readable 输入安全,重构友好(无魔术字符串)且可读
  2. Maximize performance over multiple calls 最大化多个通话的性能
  3. Provide the name of a property 提供财产名称
  4. Provide the value of the property 提供财产的价值

How can the code be improved? 如何改进代码?

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
}

You might be able to improve performance by compiling the expression tree and caching it for future use rather than calling GetValue every time. 可以通过编译表达式树并将其缓存以供将来使用,而不是每次都调用GetValue来提高性能。 However such optimizations should only be made if your current implementation causes a bottleneck. 但是,仅当您的当前实现引起瓶颈时才应进行此类优化。

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

Notice I've used a generic static type to hold the cache dictionary instance. 注意,我使用了通用静态类型来保存缓存字典实例。 This is a handy way to effectively create a separate typed cache for each distinct property type. 这是为每种不同的属性类型有效创建单独的类型化缓存的便捷方法。

It's a long story and I guess there is still no single approach that is better than others. 这是一个漫长的故事,我想仍然没有一种方法能比其他方法更好。 I think that expressions will not make a performance bottle-neck in most usual business scenarios (and you can optimize a small piece of code that need faster notifications later if you ever need it), so this approach should be fine. 我认为在大多数通常的业务场景中,表达式不会成为性能瓶颈(并且您可以优化一小段代码,如果需要的话,稍后需要更快的通知),因此这种方法应该不错。

Just keep in mind that creating expression tree is much more time-consuming that parsing it, so make sure that you do this only once (ie by using static class-level expression variables). 请记住,创建表达式树比解析它要花费更多的时间,因此请确保只执行一次(即使用静态类级别的表达式变量)。 However, your model code becomes a bit bloated in that case. 但是,在这种情况下,您的模型代码会有点肿。

I personally prefer using string-based INPC handling. 我个人更喜欢使用基于字符串的INPC处理。 ReSharper works fine with strings when it comes to refactoring, so I can call it relatively safe. ReSharper在进行重构时可以很好地与字符串配合使用,因此我可以说它相对安全。 As far as I know, this is the fastest approach. 据我所知,这是最快的方法。 And using VS or ReSharper snippets, you can easily write your properties in several keystrokes. 使用VS或ReSharper片段,您可以通过几次按键轻松地编写属性。

Regarding the property value - it is not used neither by INotifyPropertyChanging nor by INotifyPropertyChanged interface. 关于属性值-INotifyPropertyChangingINotifyPropertyChanged接口均未使用它。 Why do you need it? 你为什么需要它?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM