zoukankan      html  css  js  c++  java
  • 转载:如何优雅的实现INotifyPropertyChanged接口

    转载来源:http://www.cnblogs.com/TianFang/p/6240933.html

    INotifyPropertyChanged接口在WPF或WinFrom程序中使用还是经常用到,常用于通知界面属性变更。标准写法如下:

        class NotifyObject : INotifyPropertyChanged
        {
            private int number;
            public int Number
            {
                get { return number; }
                set { number = value; OnPropertyChanged("Number"); }
            }

            private string text;
            public string Text
            {
                get { return text; }
                set { text = value; OnPropertyChanged("Text"); }
            }

            public event PropertyChangedEventHandler PropertyChanged;
            protected void OnPropertyChanged(string propertyName = "")
            {
                PropertyChangedEventHandler handler = PropertyChanged;
                if (handler != null)
                {
                    handler(this, new PropertyChangedEventArgs(propertyName));
                }
            }
        }

    这种写法的两个问题是

    1. 对属性名使用了字符串硬编码,容易写错,也不方便重构
    2. 冗余代码,如果属性较多的时候写得想吐

     我在博客文章使用CallerMemberName简化InotifyPropertyChanged的实现中介绍了通过Caller Information解决属性名称字符串硬编码的问题。但是仍然不能解决冗余代码的问题。对于第二个问题,往往是通过AOP的方式实现,一般的实现方式有两种:

    1. 通过代理对象封装
    2. 通过编译期间代码注入的方式实现

    我增在项目中使用过DynamicObject封装来实现过,主要原理是用实现一个PocoNotifyWrapper的DynamicObject类,托管其属性的读写动作,并附加IntofyPropertyChanged接口实现。

    这种方式是动态的AOP了,是一个通用的方式,并且扩展性比较器,可以通过继承PocoNotifyWrapper来实现多态。用它做ViewMode层还是比较方便。

    不过一个不大好的地方是DynamicObject是丢失了属性类型信息的,有时绑定时会出错(如将一个TextBox的Text绑定到一个封装后的Int类型对象时会不进行自动类型转换)。要解决它还需要实现一些其它的接口,实现起来还是有些复杂的,并且项目进度比较紧张,没有太多时间来完善它。

    另外一种方式是通过编译期间代码注入方式来实现:


    最开始见的是PostSharp的一个实现: http://doc.postsharp.net/inotifypropertychanged-add。不过PostSharp是收费的,后来也逐渐由了许多其它的免费的解决方案。本文这里介绍的是一个开源的解决方案:Fody

    使用它非常简单,首先通过Nuget安装库:PM> Install-Package PropertyChanged.Fody。然后在需要实现属性通知的类上加一个[ImplementPropertyChanged]即可:

    ]
      public class Person
      {

        public string GivenNames { get; set; }
        public string FamilyName { get; set; }

        public string FullName => string.Format("{0} {1}", GivenNames, FamilyName);
      }

    编译后生成的代码如下:

     View Code

    基本上对代码没有注入,不需要安装插件,也不影响调试,实现非常简单,非常方便。

    需要注意的是,如果实现了INotifyPropertyChanged接口,即使没有[ImplementPropertyChanged]标记,默认也会注入。另外,如果要实现更多的控制,可以参看如下链接:

    除此之外,还有许多关于实现的INotifyPropertyChanged文章,感兴趣的朋友可以看一下:

  • 相关阅读:
    P1121 环状最大两段子段和
    无题
    cdoj 1485 柱爷搞子串 sam treap
    自然数幂和
    Gym 100341C AVL Trees NTT
    线性筛分解质因子
    codeforces 366 Ant Man dp
    UVALive 6914 Maze Mayhem 轮廓线dp
    hdu 5790 Prefix 字典树 主席树
    莫比乌斯反演个人小结
  • 原文地址:https://www.cnblogs.com/zhiguzhidao/p/10720794.html
Copyright © 2011-2022 走看看