gpt4 book ai didi

wpf - 在没有魔术字符串的情况下实现 NotifyPropertyChanged

转载 作者:行者123 更新时间:2023-12-03 13:52:02 25 4
gpt4 key购买 nike

这个问题在这里已经有了答案:




9年前关闭。




Possible Duplicate:
typesafe NotifyPropertyChanged using linq expressions



我正在开发一个大型团队应用程序,该应用程序大量使用 NotifyPropertyChanged("PropertyName") 形式的魔术字符串。 , - 咨询 Microsoft 时的标准实现。我们还遇到了大量错误命名的属性(使用具有数百个存储计算属性的计算模块的对象模型)——所有这些都绑定(bind)到 UI。

我的团队遇到了许多与属性名称更改相关的错误,这些错误会导致不正确的魔术字符串和破坏绑定(bind)。我希望通过在不使用魔术字符串的情况下实现属性更改通知来解决这个问题。我为 .Net 3.5 找到的唯一解决方案涉及 lambda 表达式。 (例如: Implementing INotifyPropertyChanged - does a better way exist?)

我的经理非常担心从
set { ... OnPropertyChanged("PropertyName"); }


set {  ... OnPropertyChanged(() => PropertyName); }

从中提取名称的位置
protected virtual void OnPropertyChanged<T>(Expression<Func<T>> selectorExpression)
{
MemberExpression body = selectorExpression.Body as MemberExpression;
if (body == null) throw new ArgumentException("The body must be a member expression");
OnPropertyChanged(body.Member.Name);
}

考虑一个像电子表格这样的应用程序,其中当参数发生变化时,大约有一百个值会在 UI 上实时重新计算和更新。进行此更改是否会如此昂贵以至于会影响 UI 的响应能力?我什至无法证明现在测试此更改是合理的,因为在各种项目和类中更新属性 setter 需要大约 2 天的时间。

最佳答案

我对 NotifyPropertyChanged 进行了彻底的测试,以确定切换到 lambda 表达式的影响。

这是我的测试结果:

enter image description here

正如你所看到的,使用 lambda 表达式比普通的硬编码字符串属性更改实现慢大约 5 倍,但用户不应该担心,因为即使这样,它也能够在我的服务器上每秒输出十万个属性更改。这么特别的工作电脑。因此,不再需要对字符串进行硬编码并且能够拥有处理所有业务的单行 setter 所获得的好处远远超过了我的性能成本。

测试 1 使用标准的 setter 实现,并检查属性是否实际发生了变化:

    public UInt64 TestValue1
{
get { return testValue1; }
set
{
if (value != testValue1)
{
testValue1 = value;
InvokePropertyChanged("TestValue1");
}
}
}

测试 2 非常相似,增加了一个功能,允许事件跟踪旧值和新值。因为这个特性将隐含在我的新基本 setter 方法中,所以我想看看有多少新开销是由于该特性造成的:
    public UInt64 TestValue2
{
get { return testValue2; }
set
{
if (value != testValue2)
{
UInt64 temp = testValue2;
testValue2 = value;
InvokePropertyChanged("TestValue2", temp, testValue2);
}
}
}

测试 3 是橡胶与道路相遇的地方,我将展示这种新的漂亮语法,用于在一行中执行所有可观察的属性操作:
    public UInt64 TestValue3
{
get { return testValue3; }
set { SetNotifyingProperty(() => TestValue3, ref testValue3, value); }
}

实现

在我的 BindingObjectBase 类中,所有 ViewModel 最终都继承了该类,其中包含驱动新功能的实现。我已经去掉了错误处理,所以函数的内容很清楚:
protected void SetNotifyingProperty<T>(Expression<Func<T>> expression, ref T field, T value)
{
if (field == null || !field.Equals(value))
{
T oldValue = field;
field = value;
OnPropertyChanged(this, new PropertyChangedExtendedEventArgs<T>(GetPropertyName(expression), oldValue, value));
}
}
protected string GetPropertyName<T>(Expression<Func<T>> expression)
{
MemberExpression memberExpression = (MemberExpression)expression.Body;
return memberExpression.Member.Name;
}

所有三种方法都在 OnPropertyChanged 例程中相遇,这仍然是标准:
public virtual void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(sender, e);
}

奖金

如果有人好奇,PropertyChangedExtendedEventArgs 是我刚刚想出的扩展标准 PropertyChangedEventArgs 的东西,因此扩展的实例总是可以代替基础。当使用 SetNotifyingProperty 更改属性时,它会利用旧值的知识,并将此信息提供给处理程序。
public class PropertyChangedExtendedEventArgs<T> : PropertyChangedEventArgs
{
public virtual T OldValue { get; private set; }
public virtual T NewValue { get; private set; }

public PropertyChangedExtendedEventArgs(string propertyName, T oldValue, T newValue)
: base(propertyName)
{
OldValue = oldValue;
NewValue = newValue;
}
}

关于wpf - 在没有魔术字符串的情况下实现 NotifyPropertyChanged,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7728465/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com