明確な答えを出すのは難しいですが、次のような高次の関数を実装することで、もう少し拡張可能にすることができます。
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プロパティを使用するのではなく、必要に応じて検索クエリを変更できます。たとえば、CustomerIDではなくFileIDでFileオブジェクトを取得する場合は、次のようにします。
var model = _repo.GetBy(f => f.FileId == someId);
変更する必要があるのは、コードの唯一の部分です。
C#での高階関数と関数型プログラミングに関するいくつかの本当に良い情報はここにあります:http://www.codeproject.com/Articles/375166/Functional-programming-in-Csharp
編集:
デコレータスタイルのパターンを使用して、「DBをヒットするときに常に顧客IDを使用する」を独自のリポジトリに分離できる可能性があります。したがって、次のようになります。 )。
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」式を最終的にデータベースに渡されるものに移植します。そしてもちろん、ベースリポジトリの使用のみを気にするものなら何でもそうすることができます。