You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 06:23:15