【发布时间】:2021-12-02 19:25:45
【问题描述】:
我正在寻找创建一个漂亮的帮助函数来比较两个值,如果它们不同则返回 true,并且还将第一个值更新为等于第二个值。这是我想出的:
bool UpdateHelper<T>(ref T originalProperty, T newProperty) =>
!Equals(originalProperty, newProperty) && (originalProperty = newProperty) is T _;
bool changes = false;
changes |= UpdateHelper(ref name, frmName.Text);
changes |= UpdateHelper(ref description, frmDescription.Text);
...
目标是在对几十个属性执行此操作时,避免为每个属性复制粘贴相同的 5 行代码:
if (myModel.SomeProperty != someUserInput.Text)
{
myModel.SomeProperty = someUserInput.Text
changes = true
}
(尤其是在看到有人复制粘贴并更新 if 语句部分但忘记更新赋值之后!)
我上面的助手大部分都可以工作,但不幸的是,当我尝试在属性上使用它时,它就崩溃了:
changes |= UpdateHelper(ref myModel.Name, frmName.Text);
changes |= UpdateHelper(ref myModel.Description, frmDescription.Text);
属性访问返回临时值。 'ref' 参数必须是可赋值的变量、字段或数组元素
谁能想到一个对两者都适用的解决方案?
我试着玩弄表达式,例如:
bool UpdateHelper<T>(Expression<Func<T>> originalProperty, T newProperty) =>
!Equals(originalProperty.Compile().Invoke(), newProperty) && (originalProperty.Body.??? = newProperty) is T _;
changes |= UpdateHelper(() => myModel.Name, frmName.Text);
changes |= UpdateHelper(() => myModel.Description, frmDescription.Text);
changes |= UpdateHelper(() => myModel.ChildObject.Name, frmChildName.Text);
但我觉得它会变成解析表达式树的噩梦,特别是如果它需要处理访问嵌套在下面几层的属性的特殊情况(如上面的最后一个示例)。
任何人想如何优雅地做到这一点?
【问题讨论】:
标签: c# lambda reflection linq-expressions