ASP.NET Core SignalR中如何序列化发送含抽象类子类的对象
解决SignalR序列化抽象类子类属性的问题
方案一:给System.Text.Json开启多态支持
SignalR默认使用System.Text.Json处理序列化,它不会自动识别抽象类的子类,导致子类独有的属性被截断。直接在配置中添加多态规则即可解决:
- 在
Program.cs中配置SignalR的Json协议:
builder.Services.AddSignalR() .AddJsonProtocol(options => { options.PayloadSerializerOptions.TypeInfoResolver = new DefaultJsonTypeInfoResolver { Modifiers = { typeInfo => { if (typeInfo.Type == typeof(WidgetData)) { typeInfo.PolymorphismOptions = new JsonPolymorphismOptions { TypeDiscriminatorPropertyName = "$type", // 新增类型标识字段,客户端靠这个区分子类 IgnoreUnrecognizedTypeDiscriminators = true, DerivedTypes = { new JsonDerivedType(typeof(ValueIndicatorData), nameof(ValueIndicatorData)), // 把所有WidgetData的子类都添加到这里 // new JsonDerivedType(typeof(XXXData), nameof(XXXData)) } }; } } } }; });
- Angular客户端根据
$type字段转换对应类型:
先定义好TypeScript接口:
interface WidgetData { widgetUsageId: string; timestamp: string; $type?: string; } interface ValueIndicatorData extends WidgetData { valueIndicatorValues: ValueIndicatorValue[]; } interface ValueIndicatorValue { // 对应C#类的属性 }
再处理收到的数据:
handleDashboardData(dataBatch: { dashboardId: string; widgetData: WidgetData[]; refreshDate: string }) { const typedWidgets = dataBatch.widgetData.map(item => { switch(item.$type) { case 'ValueIndicatorData': return item as ValueIndicatorData; // 其他子类的判断case按需添加 default: return item; } }); }
方案二:改用Newtonsoft.Json处理序列化
如果觉得System.Text.Json的配置繁琐,可以切换到对多态支持更成熟的Newtonsoft.Json:
- 安装NuGet包:
Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson - 在
Program.cs中配置SignalR使用NewtonsoftJson:
builder.Services.AddSignalR() .AddNewtonsoftJsonProtocol(options => { options.PayloadSerializerSettings.TypeNameHandling = TypeNameHandling.Auto; // 也可选择TypeNameHandling.Objects,根据实际需求调整 });
- 客户端同样通过返回的
$type字段区分类型,处理逻辑和方案一一致。
方案三:手动添加类型标识(无需修改全局配置)
不想改动全局序列化配置的话,可以直接在父类中新增类型标识属性,让每个子类自行返回类型名称:
- 修改C#类:
public abstract class WidgetData { public Guid WidgetUsageId { get; set;} public DateTime Timestamp { get; set;} public abstract string WidgetType { get; } // 子类必须实现该属性 } public class ValueIndicatorData : WidgetData { public override string WidgetType => nameof(ValueIndicatorData); public IList<ValueIndicatorValue> ValueIndicatorValues { get; } = new List<ValueIndicatorValue>(); }
- 客户端收到数据后,根据
widgetType字段判断类型,转换为对应的子类对象即可。
内容的提问来源于stack exchange,提问作者J4N
相关产品推荐
相关产品推荐

