如何通过C#实现对象的变更跟踪 ?

咨询区

  • user137348

我有一个类包含五个属性,如果任何一个属性被改变,我希望这个类中的另一个属性(IsDirty)会被自动变更,比如下面的类。.

public class Class1
{
    bool IsDIrty {get;set;}

    string Prop1 {get;set;}
    string Prop2 {get;set;}
    string Prop3 {get;set;}
    string Prop4 {get;set;}
    string Prop5 {get;set;}
}

回答区

  • Shimmy Weitzhandler

在 .NET Standard 2.0 中已经提供了 IChangeTracking 和 IRevertibleChangeTracking 接口可以帮助你实现对象的变更跟踪,接口实现如下:

  1. IChangeTracking
class Entity : IChangeTracking
{
  string _FirstName;
  public string FirstName
  {
    get => _FirstName;
    set
    {
      if (_FirstName != value)
      {
        _FirstName = value;
        IsChanged = true;
      }
    }
  }

  string _LastName;
  public string LastName
  {
    get => _LastName;
    set
    {
      if (_LastName != value)
      {
        _LastName = value;
        IsChanged = true;
      }
    }
  }

  public bool IsChanged { get; private set; }    
  public void AcceptChanges() => IsChanged = false;
}
  1. IRevertibleChangeTracking
class Entity : IRevertibleChangeTracking
{
  Dictionary<string, object> _Values = new Dictionary<string, object>();

  string _FirstName;
  public string FirstName
  {
    get => _FirstName;
    set
    {
      if (_FirstName != value)
      {
        if (!_Values.ContainsKey(nameof(FirstName)))
          _Values[nameof(FirstName)] = _FirstName;
        _FirstName = value;
        IsChanged = true;
      }
    }
  }

  string _LastName;
  public string LastName
  {
    get => _LastName;
    set
    {
      if (_LastName != value)
      {
        if (!_Values.ContainsKey(nameof(LastName)))
          _Values[nameof(LastName)] = _LastName;
        _LastName = value;
        IsChanged = true;
      }
    }
  }

  public bool IsChanged { get; private set; }

  public void RejectChanges()
  {
    foreach (var property in _Values)
      GetType().GetRuntimeProperty(property.Key).SetValue(this, property.Value);
    AcceptChanges();
  }

  public void AcceptChanges()
  {
    _Values.Clear();
    IsChanged = false;
  }
}

可以看到,上面这种方式是可以实现的,但需要人工一行一行的键入,如何字段特别多的话,工作量还是非常大的,作为另一个选择,我建议你使用 TrackerDog 这样的开源工具包,它可以帮你一键生成模板,你只需要提供 POCO 类即可。

点评区

这种类属性的变更通知,我记得 WPF 中就提供了 INotifyPropertyChanged 接口来实现这种 MVVM 的双向绑定,确实这也是一个非常实用的特性,学习了。