这篇文章介绍了C#实现INotifyPropertyChanged接口的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
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));
}
}
}
这种写法的两个问题是
- 对属性名使用了字符串硬编码,容易写错,也不方便重构
- 冗余代码,如果属性较多的时候写得想吐
我在博客文章使用CallerMemberName简化InotifyPropertyChanged的实现中介绍了通过Caller Information解决属性名称字符串硬编码的问题。但是仍然不能解决冗余代码的问题。对于第二个问题,往往是通过AOP的方式实现,一般的实现方式有两种:
- 通过代理对象封装
- 通过编译期间代码注入的方式实现
我增在项目中使用过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]即可:
[ImplementPropertyChanged]
public class Person
{
public string GivenNames { get; set; }
public string FamilyName { get; set; }
public string FullName => string.Format("{0} {1}", GivenNames, FamilyName);
}
编译后生成的代码如下:
public class Person : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
string givenNames;
public string GivenNames
{
get { return givenNames; }
set
{
if (value != givenNames)
{
givenNames = value;
OnPropertyChanged("GivenNames");
OnPropertyChanged("FullName");
}
}
}
string familyName;
public string FamilyName
{
get { return familyName; }
set
{
if (value != familyName)
{
familyName = value;
OnPropertyChanged("FamilyName");
OnPropertyChanged("FullName");
}
}
}
public string FullName
{
get
{
return string.Format("{0} {1}", GivenNames, FamilyName);
}
}
public virtual void OnPropertyChanged(string propertyName)
{
var propertyChanged = PropertyChanged;
if (propertyChanged != null)
{
propertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
基本上对代码没有注入,不需要安装插件,也不影响调试,实现非常简单,非常方便。
需要注意的是,如果实现了INotifyPropertyChanged接口,即使没有[ImplementPropertyChanged]标记,默认也会注入。
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对得得之家的支持。如果你想了解更多相关内容请查看下面相关链接
本文标题为:C#优雅的实现INotifyPropertyChanged接口
基础教程推荐
- unity实现动态排行榜 2023-04-27
- C# windows语音识别与朗读实例 2023-04-27
- C# 调用WebService的方法 2023-03-09
- 一个读写csv文件的C#类 2022-11-06
- linux – 如何在Debian Jessie中安装dotnet core sdk 2023-09-26
- winform把Office转成PDF文件 2023-06-14
- C#控制台实现飞行棋小游戏 2023-04-22
- C# List实现行转列的通用方案 2022-11-02
- ZooKeeper的安装及部署教程 2023-01-22
- C#类和结构详解 2023-05-30