在C#中是否存在knockoutjs计算等效值?

时间:2017-04-14 15:00:25

标签: javascript c# knockout.js

我经常使用knockout.js并且我喜欢计算的observable的概念。
计算的observable被定义为其他observable的函数的想法,并且它依赖于所使用的任何可观察变量这允许非常有趣的场景,其中所有因变量一旦发生影响其他计算变量的单个可观察变化就会更新。

http://knockoutjs.com/documentation/computedObservables.html

问题使用标准库或开源库,C#是否具有相同的功能?

1 个答案:

答案 0 :(得分:3)

答案:是的,有。

接口INotifyPropertyChanged正在执行此操作,它位于System.ComponentModel命名空间中。
此接口包含PropertyChanged事件,该事件将在更改属性时触发。

C#4及以下示例

public class DataCS4 : INotifyPropertyChanged
{
    #region INotifyPropertyChanged Members

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

    #endregion

    // Represent an Observable
    private int firstNumber;
    public int FirstNumber
    {
        get { return firstNumber; }
        set
        {
            if (value == firstNumber)
                return;

            this.firstNumber = value;
            OnPropertyChanged("FirstNumber");
            OnPropertyChanged("Sum");
        }
    }

    // Represent an Observable
    private int secondNumber;
    public int SecondNumber
    {
        get { return secondNumber; }
        set
        {
            if (value == secondNumber)
                return;

            this.secondNumber = value;
            OnPropertyChanged("SecondNumber");
            OnPropertyChanged("Sum");
        }
    }

    // Represent Computed
    public int Sum { get { return FirstNumber + SecondNumber; } }
}

这是Sum两个整数的非常简单的例子 我们有FirstNumber属性,(我们可以认为它是Knockout可观察的)
我们还有SecondNumber属性(我们可以认为是Knockout可观察的) 我们有Sum属性(我们可以考虑将其作为Knockout Computed)。

现在,每次我们更改FirstNumberSecondNumber(通过调用相应的set函数)时,我们都会通知所有订阅者这些属性(通过调用OnPropertyChanged方法完成)

我们还调用OnPropertyChanged Sum属性来通知订阅者该属性的值已更改。

注意这是使用 WPF + MVVM 模式时非常常见的模式。

使用 C#5.0 C#6.0 时,您可以从新功能中受益,使代码更容易

C#5.0示例

public class DataCS5 : INotifyPropertyChanged
{
    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = null)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion

    // Represent an Observable
    private int firstNumber;
    public int FirstNumber
    {
        get { return firstNumber; }
        set
        {
            if (value == firstNumber)
                return;

            this.firstNumber = value;
            OnPropertyChanged();
            OnPropertyChanged("Sum");
        }
    }

    // Represent an Observable
    private int secondNumber;
    public int SecondNumber
    {
        get { return secondNumber; }
        set
        {
            if (value == secondNumber)
                return;

            this.secondNumber = value;
            OnPropertyChanged();
            OnPropertyChanged("Sum");
        }
    }


    // Represent Computed
    public int Sum { get { return FirstNumber + SecondNumber; } }
}

这里有两处变化

  1. protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = null),因此通过将此属性放在方法的参数之前,编译器将知道调用此方法自动生成的属性的名称,而无需手动传递属性名称,因此我们可以编写以下语句
  2. OnPropertyChanged();代表第二次修改。
  3. 注意:CallerMemberName命名空间中存在System.Runtime.CompilerServices属性

    C#6.0示例

    使用C#6.0,我们可以简化OnPropertyChanged方法的实现。

    public class DataCS6 : INotifyPropertyChanged
    {
        #region INotifyPropertyChanged Members
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        // C# 6.0
        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    
        #endregion
    
        // Represent an Observable
        private int firstNumber;
        public int FirstNumber
        {
            get { return firstNumber; }
            set
            {
                if (value == firstNumber)
                    return;
    
                this.firstNumber = value;
                OnPropertyChanged();
                OnPropertyChanged("Sum");
            }
        }
    
        // Represent an Observable
        private int secondNumber;
        public int SecondNumber
        {
            get { return secondNumber; }
            set
            {
                if (value == secondNumber)
                    return;
    
                this.secondNumber = value;
                OnPropertyChanged();
                OnPropertyChanged("Sum");
            }
        }
    
        // Represent Computed
        public int Sum => FirstNumber + SecondNumber;
    }
    

    Reference

    更新
    回应以下评论:

      

    有趣!但是在这里你必须自己管理你的依赖。您必须触发为Sum更改的属性。在淘汰赛中,它自己计算出哪些属性将触发计算机上的属性更改。这样做的任何方式?

    我认为你可以有两个选择(至少)

    1. PropertyChanged library on GitHub
      该库的描述是:

        

      在编译时将INotifyPropertyChanged代码注入属性

      Nuget

      下载库后,这是新代码
      [PropertyChanged.ImplementPropertyChanged]
      public class Data
      {
          public int FirstNumber { get; set; }
      
          public int SecondNumber { get; set; }
      
          public int Sum => SecondNumber + FirstNumber;
      }
      

      2。PostSharp Library


    2. 干杯!。