如何使用依赖注入执行通用存储库

Fix*_*xer 7 c# asp.net-mvc repository-pattern

我已经设置了我的通用存储库,如下所示:

public interface IRepository<T> : IDisposable where T : Entity
{
    T GetById(int id);
}

public abstract class Repository<T> : IRepository<T> where T : Entity
{
    protected readonly SqlDbContext _context = new SqlDbContext();

    public T GetById(int id)
    {
        return _context.Set<T>().Find(id);
    }   
}
Run Code Online (Sandbox Code Playgroud)

为了在我的MVC应用程序中启用依赖项注入,我还创建了一个Product接口,因为签名不同.其他存储库也是如此.

public interface IProductRepository : IRepository<Product>
{
    IEnumerable<Product> GetDiscountedProducts();
}
Run Code Online (Sandbox Code Playgroud)

和实现(注意继承)

public class ProductRepository : Repository<Product>, IProductRepository
{
    public IEnumerable<Product> GetDiscountedProducts()
    {
        return _context.Set<Product>().Where(x=>x)...
    }           
}
Run Code Online (Sandbox Code Playgroud)

最后,使用unity将存储库注入MVC​​控制器

public HomeController(IProductRepository repository)
{
}
Run Code Online (Sandbox Code Playgroud)

这只是我还是这个继承链在这里有点乱?有没有办法改进这个设计?

sll*_*sll 6

我建议避免IProductRepository这种特殊情况(当简单地添加单个和非常具体的方法时)并增强原始IRepository接口,如下所示:

public interface IRepository<TEntity> : IDisposable 
                 where TEntity : Entity 
{     
   TEntity GetById(int id); 
   IEnumerable<TEntity> List(IFilterCriteria criteria);
} 
Run Code Online (Sandbox Code Playgroud)

然后实施

public sealed class ProductDiscountFilterCriteria : IFilterCriteria 
{
   // ...
}
Run Code Online (Sandbox Code Playgroud)

但在这种情况下,您需要定义一些逻辑来将条件转换为查询,它可能是一个LINQ表达式,因为您已经在使用LINQ.如果这种creteria表达方法对你的情况来说很复杂 - 我建议坚持你提出的方法.

编辑: IFilterCriteria简单的查询对象模式实现

interface IFilterCriteria<TQuery>
{
   TQuery ToQuery();
}

public sealed class ProductDiscountFilterCriteria : IFilterCriteria<DynamicExpression>
{
  public decimal Discount { get; private set; }

  public DynamicExpression ToQuery()
  {
    // build expression for LINQ clause Where("Discount" > this.Discount)
  }
}
Run Code Online (Sandbox Code Playgroud)

OR原始SQL条件构建器:

public sealed class ProductDiscountFilterCriteria : IFilterCriteria<string>
{
  public decimal Discount { get; private set; }

  public string ToQuery()
  {
    // simplified
    return "WHERE Discount < " + this.Discount;
  }
}
Run Code Online (Sandbox Code Playgroud)

那么你就可以像以下一样使用它:

var products = productRepository.List<Product>(
                             new DiscountFilterCriteria { Discount = 50 });
Run Code Online (Sandbox Code Playgroud)

动态LINQ示例和文章: