gpt4 book ai didi

c# - 是否可以创建通用 API GET 操作?

转载 作者:太空狗 更新时间:2023-10-30 01:29:36 24 4
gpt4 key购买 nike

最近我创建了一个服务,它在我的 API 中有一些逻辑用于 GET 端点(返回一些数据库表的所有值)。

为此创建服务的原因是我想一次性修改 GET 逻辑,而不是将来必须在我的所有端点上更改它。

我创建了一个有效的测试服务,但因为我有 50 多个表(DTO 类),所以我想让该服务更通用。

我现在已经实现了以下,这只是一个 DTO 类的一个 GET 操作的示例:

public interface IOMSService
{
IEnumerable<CommodityViewModel> GetAll(); // Can I use <T> for this? - now I need to make interface properties for every OMS class (50+)
}

public class OMSService : IOMSService
{
private MyDBContext _context;
private IMapper _mapper;

public OMSService(MyDBContext context, IMapper mapper)
{
_context = context;
_mapper = mapper;
}

public IEnumerable<CommodityViewModel> GetAll() // How to make this more generic?
{
var result = this._context.Commodity
.Include(i => i.OmsCommodityMaterial);

var CommodityVM = _mapper.Map<IList<CommodityViewModel>>(result);

return CommodityVM;

}
}

上面的示例有效,但是,这意味着我需要为每个 DTO 类实现 50 多个接口(interface)属性和 50 个 GetAll 实现(因此与在端点中更改它相比,这不是改进本身)。

有没有办法让它更通用?我认为接口(interface)中 IEnumerable 的 DTO 部分和 GetAll 函数应该是通用类型(这样我就可以在端点本身提供正确的 ViewModel/DTO ).

我已经想到了这样的事情:

public interface IOMSService<T, U>
where T : IEnumerable<U>
{
T GetAll { get; }
}

有人能给我指出正确的方向吗?

最佳答案

是的,使用泛型和 Set<T>() DbContext的方法| ,你可以这样做:

//Note we need to make the entity and the model it maps to generic
public IEnumerable<TModel> GetAll<TEntity, TModel>(
params Expression<Func<TEntity, object>>[] includes)
where TEntity : class
{
var result = _context.Set<TEntity>().AsQueryable();

if(includes != null)
{
foreach (var include in includes)
{
result = result.Include(include);
}
}

return _mapper.Map<IList<TModel>>(result);
}

然后这样调用它:

var allTheThings = GetAll<Commodity, CommodityViewModel>(i => i.OmsCommodityMaterial);

但是,返回所有您的行几乎肯定不是一个好主意,所以为什么不在我们这里添加过滤器:

public IEnumerable<TModel> Get<TEntity, TModel>(
Expression<Func<TEntity, bool>> predicate,
params Expression<Func<TEntity, object>>[] includes)
where TEntity : class
{
var result = _context.Set<TEntity>()
.Where(predicate);

if(includes != null)
{
foreach (var include in includes)
{
result = result.Include(include);
}
}

return _mapper.Map<IList<TModel>>(result);
}

现在我们这样调用它:

var someOfTheThings = Get<Commodity, CommodityViewModel>(
x => x.SomeProperty == 42,
i => i.OmsCommodityMaterial);

如果你想从这个方法中提取一个接口(interface),我可能会把接口(interface)变成通用的:

public interface IOMSService<TEntity>
{
IEnumerable<TModel> Get<TModel>(
Expression<Func<TEntity, bool>> predicate,
params Expression<Func<TEntity, object>>[] includes)
}

然后是一个基类:

public abstract class BaseOMSService<TEntity> : IOMSService<TEntity>
where TEntity : class
{
private MyDBContext _context;
private IMapper _mapper;

public BaseOMSService(MyDBContext context, IMapper mapper)
{
_context = context;
_mapper = mapper;
}

public IEnumerable<TModel> Get<TModel>(
Expression<Func<TEntity, bool>> predicate,
params Expression<Func<TEntity, object>>[] includes)
{
var result = _context.Set<TEntity>()
.Where(predicate);

if(includes != null)
{
foreach (var include in includes)
{
result = result.Include(include);
}
}

return _mapper.Map<IList<TModel>>(result);
}
}

现在您可以创建特定的派生类:

public class CheeseOMSService : BaseOMSService<Cheese>
{
// snip
}

public class ZombieOMSService : BaseOMSService<Zombie>
{
// snip
}

关于c# - 是否可以创建通用 API GET 操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51158002/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com