我经常使用knockout.js并且我喜欢计算的observable的概念。
计算的observable被定义为其他observable的函数的想法,并且它依赖于所使用的任何可观察变量这允许非常有趣的场景,其中所有因变量一旦发生影响其他计算变量的单个可观察变化就会更新。
http://knockoutjs.com/documentation/computedObservables.html
问题:使用标准库或开源库,C#是否具有相同的功能?
答案 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)。
现在,每次我们更改FirstNumber
或SecondNumber
(通过调用相应的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; } }
}
这里有两处变化
protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = null)
,因此通过将此属性放在方法的参数之前,编译器将知道调用此方法自动生成的属性的名称,而无需手动传递属性名称,因此我们可以编写以下语句OnPropertyChanged();
代表第二次修改。 注意: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;
}
更新
回应以下评论:
有趣!但是在这里你必须自己管理你的依赖。您必须触发为Sum更改的属性。在淘汰赛中,它自己计算出哪些属性将触发计算机上的属性更改。这样做的任何方式?
我认为你可以有两个选择(至少)
PropertyChanged library on GitHub。
该库的描述是:
下载库后,这是新代码在编译时将INotifyPropertyChanged代码注入属性
[PropertyChanged.ImplementPropertyChanged]
public class Data
{
public int FirstNumber { get; set; }
public int SecondNumber { get; set; }
public int Sum => SecondNumber + FirstNumber;
}
干杯!。