很难给出明确的答案,但您可以通过实现更高阶的函数使其更具可扩展性,如下所示:
public interface IRepository<T>
{
public T GetBy(Expression<Func<T, bool>> query)
}
public class FileRepository : IRepository<File>
{
public File GetBy(Expression<Func<T, bool>> query)
{
using(var context = new FilesContext())
{
return context.Files.Where(query).FirstOrDefault();
}
}
}
public class SomeController
{
private IRepository<File> _repo;
public SomeController(IRepository<File> repo)
{
_repo = repo;
}
public ActionResult Index()
{
var model = _repo.GetBy(f => f.CustomerId == Session.Whatever.CustomerId);
return View(model);
}
}
这样,您可以在需要时更改搜索查询,而不是使用硬编码的客户 ID 属性。例如,如果您想通过 FileID 而不是 CustomerID 获取 File 对象,那么:
var model = _repo.GetBy(f => f.FileId == someId);
这是代码中唯一需要更改的部分。
这里有一些关于高阶函数和 C# 函数式编程的非常好的信息:http://www.codeproject.com/Articles/375166/Functional-programming-in-Csharp
编辑:
您可以使用装饰器样式模式将“在访问 DB 时始终使用客户 ID”隔离到它自己的存储库中,因此:(massive 免责声明 - 我没有对此进行了测试,但是这些方面的东西应该可以工作)
public class SpecialFileRepo : IRepository<File>
{
private readonly IRepository<File> _baseRepo;
public SpecialFileRepo(IRepository<File> baseRepo)
{
_baseRepo = baseRepo;
}
public SpecialFileRepo() : this(new FileRepository())
{
}
public File GetBy(Expression<Func<File, bool>> query)
{
var parameters = query.Parameters;
var newParam = Expression.Parameter(typeof (File), "f");
var additionalQuery = Expression.AndAlso(query.Body,
Expression.Equal(
Expression.PropertyOrField(newParam, "CustomerId"),
Expression.Constant(HttpContext.Current.Session["customerId"])));
var newQuery = query.Update(additionalQuery, parameters);
return _baseRepo.GetBy(newQuery);
}
}
然后任何与存储库对话的东西,就它而言,它只是一个基本存储库,但是这个类位于两者之间,并且总是将“customerid = sessionwhatever”表达式嫁接到最终传递给数据库的内容上。当然,任何只关心使用基础存储库的东西,仍然可以这样做。