如何为抽象基类Thing实现带动态枚举的IsInList方法(适配Blazor)
问题描述
我有不同类型的Item,每种Item都有存储ID的枚举。希望为抽象基类Thing实现一个方法用于检查Item的ID是否在指定列表中,但不想采用Thing<T>泛型基类方案(避免Blazor UI组件和页面代码混乱)。同时需要实现:
- Blazor组件接收
Thing类型参数,统一展示所有子类实例 - 在页面中直接调用
Thing实例的IsInList方法判断是否在指定列表中
原示例代码存在编译问题,核心是要在非泛型基类的前提下,让子类各自处理枚举ID的校验逻辑。
可行实现方案
1. 重构抽象基类
将ID定义为object类型,IsInList方法接收非泛型IEnumerable参数,让子类自行处理类型匹配:
public abstract class Thing { public string Name { get; set; } public int Amount { get; set; } // 子类返回自身的枚举ID public abstract object ID { get; } // 检查当前ID是否在目标列表中 public abstract bool IsInList(IEnumerable list); }
2. 子类具体实现(以Fruit为例)
子类定义自身枚举,实现基类的ID属性和IsInList方法,先做类型校验再检查包含关系:
public class Fruit : Thing { public enum FruitIds { F_NotSet, F_Banana, F_Apple } public FruitIds CurrentId { get; set; } = FruitIds.F_NotSet; // 实现基类ID属性,返回当前枚举值 public override object ID => CurrentId; public override bool IsInList(IEnumerable list) { // 校验列表类型是否匹配当前枚举 if (list is List<FruitIds> fruitList) { return fruitList.Contains(CurrentId); } return false; } }
3. Blazor UI组件(ThingViewer)
组件直接接收Thing类型参数,展示通用属性:
<div>@Thing.Name [@Thing.Amount]</div> @code { [Parameter] public Thing Thing { get; set; } }
4. 页面复用组件与调用IsInList
页面维护List<Thing>实例和对应枚举列表,循环调用即可:
<div> @foreach (var thing in MyThings) { @if (thing.IsInList(OfferFruitIds)) { <div class="offer"> <ThingViewer Thing="thing" /> </div> } else { <ThingViewer Thing="thing" /> } } </div> @code { private List<Thing> MyThings = new List<Thing> { new Fruit { Name = "香蕉", Amount = 10, CurrentId = Fruit.FruitIds.F_Banana }, new Fruit { Name = "苹果", Amount = 5, CurrentId = Fruit.FruitIds.F_Apple } }; // 优惠的水果ID列表 private List<Fruit.FruitIds> OfferFruitIds = new List<Fruit.FruitIds> { Fruit.FruitIds.F_Banana }; }
可选优化:类型安全重载
为了避免直接传IEnumerable的类型模糊,可给基类增加泛型重载方法,子类无需修改即可支持类型安全调用:
public abstract class Thing { // ... 原有成员 // 类型安全的重载入口,默认调用非泛型版本 public bool IsInList<T>(IEnumerable<T> list) { return IsInList((IEnumerable)list); } }
页面中可直接用类型安全的方式调用:thing.IsInList(OfferFruitIds)
内容的提问来源于stack exchange,提问作者javirs
相关产品推荐
相关产品推荐

