Blazor WASM中通过反射复制对象属性实现保存/撤销功能遇阻
问题分析与解决
核心错误
你的反射代码存在一个关键错误:SetValue的目标实例传错了。当前代码是把selectedMessageTemp的属性值重新赋值回它自己,完全没有修改selectedMessage。
错误代码片段:
selectedMessage?.GetType().GetProperty(propertyName)?.SetValue(selectedMessageTemp, propertyValue);
这里的第二个参数应该是selectedMessage,而非selectedMessageTemp。
修正后的反射代码
if (selectedMessage != null && selectedMessageTemp != null) { PropertyInfo[] properties = selectedMessageTemp.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (PropertyInfo property in properties) { // 跳过只读属性,避免赋值报错 if (!property.CanWrite) continue; object? value = property.GetValue(selectedMessageTemp); selectedMessage.GetType().GetProperty(property.Name)?.SetValue(selectedMessage, value); } }
额外优化点:
- 明确指定绑定标志,避免获取静态属性
- 跳过只读属性,防止设置只读属性时抛出异常
为什么直接赋值selectedMessage = selectedMessageTemp不生效?
在Blazor WASM中,组件UI绑定依赖对实例内部状态变化的追踪。如果直接替换selectedMessage的引用,Blazor默认不会检测到该变化(除非手动调用StateHasChanged())。而QuickGrid绑定的是原列表中的实例引用,替换引用无法让网格感知到更新,必须修改原有实例的属性值才能触发UI刷新。
更优替代方案
反射虽能批量赋值,但存在性能开销且不够直观,推荐两种更可靠的方式:
1. 在实体类中实现复制方法
在你的Message类中编写CopyFrom方法,手动控制需要复制的属性,比反射更可控:
public class Message { public string? Subject { get; set; } public string? Content { get; set; } // 其他属性... public void CopyFrom(Message source) { Subject = source.Subject; Content = source.Content; // 逐个复制需要同步的属性 } }
使用时直接调用:
selectedMessage?.CopyFrom(selectedMessageTemp);
2. 使用AutoMapper简化映射
如果项目已使用AutoMapper,可配置映射规则后一键复制:
// 配置(可放在启动逻辑中) var config = new MapperConfiguration(cfg => cfg.CreateMap<Message, Message>()); var mapper = config.CreateMapper(); // 使用 mapper.Map(selectedMessageTemp, selectedMessage);
内容的提问来源于stack exchange,提问作者Robin Wilson
相关产品推荐
相关产品推荐

