最近,我创建了一个服务,该服务在我的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多个接口属性和50个GetAll
实现(因此,与在端点本身中进行更改相比,这不是一种改进)。
有没有办法使它更通用?
我认为接口IEnumerable
中的GetAll
的DTO部分应该是Generic类型的(这样我就可以在端点本身上提供正确的ViewModel / DTO)。
我已经想出了这样的东西:
public interface IOMSService<T, U>
where T : IEnumerable<U>
{
T GetAll { get; }
}
有人可以指出我正确的方向吗?
答案 0 :(得分:3)
是的,使用泛型和Set<T>()
的{{1}}方法,您可以执行以下操作:
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);
}
但是,要返回 all 行几乎是一个坏主意,所以为什么不在我们这里时添加过滤器:
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);
然后是基类:
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);
}
}