如何在类中使用带泛型方法的抽象类ResourceFilter作为属性
解决方法
要解决泛型抽象类无法直接作为非泛型属性类型的问题,你需要定义一个非泛型的基础抽象类/接口,让泛型的ResourceFilter<TFilter>继承它,以此实现统一类型的声明。
步骤1:创建非泛型抽象基类
先定义一个不带泛型参数的抽象类,封装所有不依赖TFilter的核心成员:
public abstract class ResourceFilterBase : SomeOtherClass { protected ResourceFilterBase(string name, string friendlyName) : base(name, friendlyName) { } public abstract string GetFilterDisplay(object filter); public abstract string GetFilterValue(object filter); public virtual string GetComparisonValue(object compare) { return Value + "_" + GetFilterValue(compare); } public abstract object GetDefaultFilter(); }
步骤2:修改泛型抽象类继承非泛型基类
让原泛型类继承新的非泛基类,同时保留泛型版本的方法供子类实现:
public abstract class ResourceFilter<TFilter> : ResourceFilterBase { public static readonly ResourceFilter<ActorTypeEnum> ActorType = new ActorTypeResourceFilter(); protected ResourceFilter(string name, string friendlyName) : base(name, friendlyName) { } // 实现非泛型基类方法,内部转调泛型版本 public override string GetFilterDisplay(object filter) { return GetFilterDisplay(TypeCheck(filter)); } public override string GetFilterValue(object filter) { return GetFilterValue(TypeCheck(filter)); } public override object GetDefaultFilter() { return GetDefaultFilterTyped(); } // 泛型版本的抽象方法,供子类实现具体逻辑 public abstract string GetFilterDisplay(TFilter filter); public abstract string GetFilterValue(TFilter filter); public abstract TFilter GetDefaultFilterTyped(); protected TFilter TypeCheck(object value) { if (value is null) throw new ArgumentNullException(nameof(value)); if (value is TFilter expectedType) return expectedType; throw new FriendlyException($"Type {value.GetType()} is not valid for this Resource Filter"); } }
步骤3:调整实现类逻辑
修改ActorTypeResourceFilter,实现泛型版本的抽象方法即可:
public sealed class ActorTypeResourceFilter : ResourceFilter<ActorTypeEnum> { internal ActorTypeResourceFilter() : base(nameof(ActorType), "Actor Type") { } public override string GetFilterDisplay(ActorTypeEnum filter) { return filter.FriendlyName; } public override string GetFilterValue(ActorTypeEnum filter) { return filter.Name; } public override ActorTypeEnum GetDefaultFilterTyped() { return ActorTypeEnum.User; } }
步骤4:在目标类中使用非泛型类型
现在就可以直接在ClassToApplyResourceFilter中用非泛型基类作为属性类型了:
public class ClassToApplyResourceFilter { public ResourceFilterBase ResourceFilter { get; private set; } }
补充说明
这种设计既保留了泛型的类型安全性(子类实现时仍针对具体TFilter做逻辑),又满足了统一类型声明的需求。如果不想修改太多原有代码,也可以用非泛型接口IResourceFilter替代抽象基类,效果一致。
内容的提问来源于stack exchange,提问作者JGillard_SynergyCloud
相关产品推荐
相关产品推荐

