刷新计算属性的依赖关系树的最佳方式是什么

本文关键字:最佳 方式 是什么 依赖 计算 属性 刷新 关系 | 更新日期: 2023-09-27 17:58:37

我这里有一些类,它们或多或少地相互依赖。关系的形式有点像依赖树:

class A {
  List<B> _bs = new List<B>();
  public int ValueOfA { 
    get {
      return _bs.Sum(p => p.ValueOfB);
    }
}
class B {
  List<C> _cs = new List<C>();
  public int ValueOfB {
    get {
      return _cs.Where(p => p.ValueOfC > 1).Sum(p => p.ValuOfC);
    }
  }
class C {
  public int ValueOfC { get; set }
}

因此,每当_bs_csValueOfC发生变化时,与它们相关的每个属性都应该被通知为也发生了变化,并因此被重新计算。

始终如一、可靠地实现这一目标的最佳方式是什么?有没有办法自动做到这一点?

刷新计算属性的依赖关系树的最佳方式是什么

您将希望用类C实现INotifyPropertyChanged。在ValueOfC集合中,您将触发事件:

class C : INotifyPropertyChanged 
{
    public event PropertyChangedEventHandler PropertyChanged;
    private int valueOfC;
    public int ValueOfC
    {
        get { return valueOfC; }
        set
        {
            valueOfC = value;
            OnPropertyChanged(PropertyChanged);
        }
    }
    protected virtual void OnPropertyChanged(PropertyChangedEventHandler handler)
    {
        if (handler != null)
            handler(this, new PropertyChangedEventArgs("ValueOfC"));
    }
}

我刚刚测试过,效果很好。

让一个受保护的虚拟方法为您触发事件只是一种常见的做法。

顺便说一句,如果你想在列表发生变化时做点什么,你可能需要考虑使用BindingList或ObservableCollection。

编辑

我写了一个刷新整棵树的小例子:

public class Bank : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private BindingList<Customer> customers = new BindingList<Customer>();
    public int Worth
    {
        get { return customers.Sum(cust => cust.FullBalance); }
    }
    public Bank()
    {
        customers.ListChanged += new ListChangedEventHandler(customers_ListChanged);
    }
    void customers_ListChanged(object sender, ListChangedEventArgs e)
    {
        Console.WriteLine("A customer has changed.");
        var handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs("Worth"));
    }
    public void Add(Customer c) { customers.Add(c); }
}
public class Customer : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private BindingList<Account> accounts = new BindingList<Account>();
    public int FullBalance
    {
        get { return accounts.Sum(acc => acc.Balance); }
    }
    public Customer()
    {
        accounts.ListChanged += new ListChangedEventHandler(accounts_ListChanged);
    }
    void accounts_ListChanged(object sender, ListChangedEventArgs e)
    {
        Console.WriteLine("An account has changed.");
        var handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs("FullBalance"));
    }
    public void Add(Account a) { accounts.Add(a); }
}
public class Account : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private int balance = 0;
    public int Balance
    {
        get { return balance; }
        set
        {
            var handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs("Balance"));
        }
    }
}
class Program
{
    static void Main(string[] args)
    {
        Account a1 = new Account() { Balance = 5 };
        Account a2 = new Account() { Balance = 10 };
        Account a3 = new Account() { Balance = 15 };
        Customer c1 = new Customer(); c1.Add(a1); c1.Add(a2);
        Customer c2 = new Customer(); c2.Add(a3);
        Bank b = new Bank(); b.Add(c1); b.Add(c2);
        Console.WriteLine();
        a1.Balance += 100;
    }
}

现在,您可以在事件处理程序中编写类似if (e.ListChangedType == ListChangedType.ItemChanged)的内容,或者类似的内容。