本文介绍了当先决条件属性在另一个类中更改时,为依赖属性提高PropertyChanged?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个家银行类:

public class Bank : INotifyPropertyChanged
{
    public Bank(Account account1, Account account2)
    {
        Account1 = account1;
        Account2 = account2;
    }

    public Account Account1 { get; }
    public Account Account2 { get; }

    public int Total => Account1.Balance + Account2.Balance;

    public event PropertyChangedEventHandler PropertyChanged = delegate { };

    public void RaisePropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

银行取决于其他类,并具有属性 Total ,该属性是根据其他类的属性计算得出的。每当更改任何 Account.Balance 属性时,都会为 Account.Balance引发 PropertyChanged

Bank depends on other classes and has a property Total that is calculated from properties of these other classes. Whenever any of these Account.Balance properties is changed, PropertyChanged is raised for Account.Balance:

public class Account : INotifyPropertyChanged
{
    private int _balance;

    public int Balance
    {
        get { return _balance; }
        set
        {
            _balance = value;
            RaisePropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged = delegate { };

    public void RaisePropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

我想筹集每当更改任何前提属性时,总计的PropertyChanged 。如何以一种易于测试的方式做到这一点?

I would like to raise PropertyChanged for Total, whenever any of the prerequisite properties is changed. How can I do this in a way that is easily testable?

TL; DR 如何提高 PropertyChanged (如果在另一个类中更改了先决条件属性),则为从属属性?

TL;DR How do I raise PropertyChanged for a dependent property, when a prerequisite property is changed in another class?

推荐答案

以许多不同的方式。我见过许多不同的解决方案,它们在单个属性 setter 中调用自定义属性或引发多个 PropertyChanged 事件。我认为其中大多数都是反模式的,并且不容易测试。

You can do this in many different ways. I have seen many different solutions, that invovle custom attributes or raising multiple PropertyChanged events in a single property setter. I think most of these soultions are anti-patterns, and not easily testable.

同事的最佳方式(),我想出了这个静态类:

The best way a colleague (Robert Jørgensgaard Engdahl) and I have come up with is this static class:

public static class PropertyChangedPropagator
{
    public static PropertyChangedEventHandler Create(string sourcePropertyName, string dependantPropertyName, Action<string> raisePropertyChanged)
    {
        var infiniteRecursionDetected = false;
        return (sender, args) =>
        {
            try
            {
                if (args.PropertyName != sourcePropertyName) return;
                if (infiniteRecursionDetected)
                {
                    throw new InvalidOperationException("Infinite recursion detected");
                }
                infiniteRecursionDetected = true;
                raisePropertyChanged(dependantPropertyName);
            }
            finally
            {
                infiniteRecursionDetected = false;
            }
        };
    }
}

它将创建 PropertyChangedEventHandler ,您可以将其设置为侦听其他类上的PropertyChanged。在抛出 StackOverflowException 之前,它使用 InvalidOperationException 处理循环依赖。

It creates a PropertyChangedEventHandler, which you can set up to listen on PropertyChanged on other classes. It handles circular dependencies with an InvalidOperationException before an StackOverflowException is thrown.

要在上面的示例中使用静态 PropertyChangedPropagator ,您将必须为每个必备属性添加一行代码:

To use the static PropertyChangedPropagator in the example from above, you will have to add one line of code for each prerequisite property:

public class Bank : INotifyPropertyChanged
{
    public Bank(Account account1, Account account2)
    {
        Account1 = account1;
        Account2 = account2;
        Account1.PropertyChanged += PropertyChangedPropagator.Create(nameof(Account.Balance), nameof(Total), RaisePropertyChanged);
        Account2.PropertyChanged += PropertyChangedPropagator.Create(nameof(Account.Balance), nameof(Total), RaisePropertyChanged);
    }

    public Account Account1 { get; }
    public Account Account2 { get; }

    public int Total => Account1.Balance + Account2.Balance;


    public event PropertyChangedEventHandler PropertyChanged = delegate { };

    public void RaisePropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

这很容易测试(伪代码):

This is easily testable (pseudo code):

[Test]
public void Total_PropertyChanged_Is_Raised_When_Account1_Balance_Is_Changed()
{
    var bank = new Bank(new Account(), new Account());

    bank.Account1.Balance += 10;

    Assert.PropertyChanged(bank, nameof(Bank.Total));
}

这篇关于当先决条件属性在另一个类中更改时,为依赖属性提高PropertyChanged?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-18 02:23