【发布时间】:2022-02-01 00:54:21
【问题描述】:
简介
我正在使用实体框架创建一个 ASP.NET Web API 应用程序。我需要做的是为一个 URI 返回同一资源的不同表示,具体取决于用户角色。例如,api/employees/1 将为管理员和标准用户返回两个不同的对象:
标准用户
public class EmployeeBasic
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
管理员
public class EmployeeExtended : EmployeeBasic
{
public decimal Salary { get; set; }
}
想法和尝试
对于每个资源表示,我需要提供一些相关的类,例如排序模型。我想知道是否可以使用泛型类型和继承来为相关表示创建通用存储库方法。我想到了以下方法:
-
为排序模型创建一些基本接口:
public interface ISortModel<out TBusinessEntity> { // } -
创建通用 SortModel 作为所有排序模型的基本类型
public abstract class SortModel<TDBEntity, TBusinessEntity> : ISortModel<TBusinessEntity> { // Database sorting public abstract IQueryable<TDBEntity> ApplyToQuery(IQueryable<TDBEntity> query); // Local sorting public abstract IEnumerable<TBusinessEntity> ApplyToLocal(IEnumerable<TBusinessEntity> localList); // ... // Some private logic (expression mappers, etc.) } -
为基本资源创建排序模型
public class EmployeeBasicSortModel : SortModel<DBModel.Employee, EmployeeBasic> { public int FullName { get; set; } public override IQueryable<DBModel.Employee> ApplyToQuery(IQueryable<DBModel.Employee> query) { // implementation } public override IEnumerable<EmployeeBasic> ApplyToLocal(IEnumerable<EmployeeBasic> localList) { // implementation } } -
扩展基本排序模型,为扩展资源属性添加排序
public class EmployeeExtendedSortModel : EmployeeBasicSortModel //, ... Is it possible to somehow do that? { public override IEnumerable<EmployeeExtended> ApplyToLocal(IEnumerable<EmployeeExtended> localList) { var partiallyOrderedList = base.ApplyToLocal(localList); // Add extended sorting } // ... ? } -
使用上述类创建通用服务:
class EmployeesService() { public IList<TEmployee> GetAll<TEmployee>(ISortModel<TEmployee> sortModel) where TEmployee : BasicEmployee { // implementation } }
问题
当我第一次想到它时,它似乎很简单。但是当我开始实现这个时,我无法弄清楚实现第 4 步的方法。要么我在我的 C# 知识中遗漏了一些东西(这很可能),要么这在我试图做到这一点的方式中是不可能的。
所以问题是:我可以创建一个具有泛型类型的基类,从它派生出基本资源作为一种类型,然后再派生一次扩展类吗?
【问题讨论】:
-
听起来过于复杂了。你想达到什么目的?
-
如果我理解正确,您是在问是否可以继承类型参数是一回事的泛型类型(例如
EmployeeBasic),然后使用不同类型覆盖成员(例如EmployeeExtended) .如果是这样,那么答案是否定的,你不能这样做,出于同样的原因,对于问同样事情的数百个其他相同的 Stack Overflow 问题,答案是“否”:它不是类型安全的。如果您要问其他问题,请编辑您的问题,以便清楚您在问什么。请务必解释为什么这是特定于 ASP.NET,因为您添加了这些标签。 -
谢谢彼得,我认为这回答了我的问题。 @Mardoxx 也许是这样,但我也给出了过于简单的例子。我有更多的类,每个类都有比示例中更多的属性。一些属性在数据库中加密,这就是为什么我需要单独的数据库和本地排序/过滤。拥有自我解决的排序/过滤模型让我可以准备一个通用查询机制,而不是每个服务方法中的一堆 if/else 语句:pastebin.com/Hsp095L8 - 这在内部使用过滤器执行查询,解密实体并应用本地排序/过滤
-
然而,在我意识到我需要为每个资源提供多个表示之前,它要方便得多。然后,我想要实现的是:(1)避免从数据库中获取扩展实体,然后将其映射到受限视图模型(这将执行不需要的 sql 查询),因此:(2)修改我的通用查询机制以支持不同的资源表示.但是,它确实似乎太复杂了,我将创建单独的服务方法或使用(1)方法。
-
不要使用继承来实现这一点,并且基于您试图操纵 行为 而不是数据的事实,为什么不使用
Func作为参数你的排序逻辑。然后您的类可以以不同的方式传递给基排序逻辑。您在基类中定义基本排序框架,然后派生类传递它们希望使用的排序行为。
标签: c#