反序列化JSON时使用带约束的C#泛型:rows属性访问及泛型参数报错问题
解决C#泛型JSON反序列化中无法访问子类属性的问题
问题原因
- 你的
GenericCouch类中,TTable的约束仅为TableBase,而TableBase并未定义rows属性,因此反序列化得到的TTable类型变量只能访问TableBase的成员,无法直接访问OrderItemDrugTable<TRow>的rows。 - 你尝试的
JsonSerializer.Deserialize<TTable<TRow>>写法错误,因为TTable是一个具体的类型参数(比如实例化时传入的OrderItemDrugTable<DrugRow>),而非泛型类型定义(如OrderItemDrugTable<>),所以不能为它附加类型参数,这就是编译器报错的核心原因。
解决方案
方案一:通过接口约束关联TTable与TRow
定义包含rows属性的接口,让OrderItemDrugTable<TRow>实现该接口,同时修改GenericCouch的泛型约束,确保TTable实现此接口:
// 定义统一接口 public interface IHasRows<TRow> where TRow : RowBase { List<TRow> rows { get; set; } } // 让OrderItemDrugTable实现接口 public class OrderItemDrugTable<TRow> : TableBase, IHasRows<TRow> where TRow : RowBase { public List<TRow> rows { get; set; } } // 修改GenericCouch的约束 public class GenericCouch<TRow, TTable> where TRow : RowBase where TTable : TableBase, IHasRows<TRow> { public void DeserializeTable(string result, JsonSerializerOptions options) { var table = JsonSerializer.Deserialize<TTable>(result, options); // 现在可直接访问rows属性 var targetRows = table.rows; } }
方案二:直接约束TTable为OrderItemDrugTable的子类
如果GenericCouch仅用于处理OrderItemDrugTable及其子类,可直接将TTable的约束设为OrderItemDrugTable<TRow>:
public class GenericCouch<TRow, TTable> where TRow : RowBase where TTable : OrderItemDrugTable<TRow> { public void DeserializeTable(string result, JsonSerializerOptions options) { var table = JsonSerializer.Deserialize<TTable>(result, options); // 直接访问rows属性 var targetRows = table.rows; } }
方案三:在TableBase中定义抽象rows属性
如果所有TableBase的子类都需要rows属性,可在基类中定义抽象属性,子类实现该属性:
public abstract class TableBase { public abstract List<RowBase> Rows { get; set; } } public class OrderItemDrugTable<TRow> : TableBase where TRow : RowBase { public List<TRow> rows { get; set; } // 实现基类抽象属性 public override List<RowBase> Rows { get => rows.Cast<RowBase>().ToList(); set => rows = value.Cast<TRow>().ToList(); } } public class GenericCouch<TRow, TTable> where TRow : RowBase where TTable : TableBase { public void DeserializeTable(string result, JsonSerializerOptions options) { var table = JsonSerializer.Deserialize<TTable>(result, options); // 通过基类属性访问,按需转换为TRow类型 var targetRows = table.Rows.Cast<TRow>().ToList(); } }
内容的提问来源于stack exchange,提问作者obautista
相关产品推荐
相关产品推荐

