У меня есть класс, к которому я постоянно добавляю.Создание класса следует за OCP - Факторинг в объектах
public class OrderRepository{
public void Add(IEnumerable<Order> orders){}
public void Update(IEnumerable<Order> orders){}
public void Remove(IEnumerable<Order> orders){}
public void Expedite(IEnumerable<Order> orders){}
public void GetOrderData(Order order, DateTime start, DateTime end)
etc...
}
Мне пришло в голову, что этот класс не является открытым Closed, из-за всех этих новых возможностей, добавленных. Поэтому я решил закрыть этот класс против этого изменения, инкапсулируя эти функции в объекты Request. В итоге я получаю что-то вроде:
public abstract class RequestBase{}
public class AddRequest : RequestBase{}
etc...
public class OrderRepository{
public void ProcessRequest(RequestBase request){}
}
Который делает OrderRepository открытым для расширения и закрыт для модификации. Тем не менее, я быстро столкнулся с несколькими проблемами с этим:
1.) Данные, на которые должен работать данный запрос, предоставляются как пользователем, так и временем выполнения. Я, очевидно, не могу удовлетворить как с одним конструктором. Я не могу:
public class AddRequest{
public AddRequest(IEnumerable<Order> orders, int UserSuppliedContextArg1, DependencyInjectionArg1, DependencyInjectionArg2);
}
и позвоните, что. Я хотел бы, чтобы рамки DI «частично» построили для меня объект, и позвольте мне сделать все остальное. Однако я не вижу никакого способа сделать это. Я увидел блог, который назвал это понятие «инъекцией конструктора переменных».
2.) Следующее, о чем я думал, это разделить его на 2 отдельных класса. Пользователь создавал и заполнял RequestContext, а затем передавал это в репозиторий, что создавало бы RequestProcessor (не может думать о более лучшем имени). Я думал о том, чтобы сделать:
и это был хороший первый шаг. Тем не менее, процессору запросов нужен точный тип контекста, который он хранит, которого у меня здесь нет. Я мог бы использовать словарь типов для типов, но поражения цели быть открыто-замкнуты .so я в конечном итоге, сделать что-то вроде:
public class RequestProcessorBase<TRequestContext, TRequestProcessorBase> where TRequestContext : RequestContextBase<TRequestProcessorBase>
Это странно, и я обычно не любят curiously recurring template pattern. Кроме того, идея пользователя, заполняющего контекст и предлагающего мне сделать запрос, кажется странным, хотя это может быть просто проблема с именами.
3.) Я думал о том, чтобы избавиться от всего вышеперечисленного и просто иметь:
public AddRequest{
public AddRequest(DependencyInjectionArg1, DependencyInjectionArg2, ...){}
public void PackArgs(UserSuppliedContextArg1, UserSuppliedContextArg2, UserSuppliedContextArg3, ...){}
}
что не плохо, но API некрасиво. Теперь клиенты этого объекта должны «сконструировать» его дважды, как это было. И если они забывают вызвать PackArgs, я должен бросить какое-то исключение.
Я мог бы продолжать, но это самые запутанные проблемы, которые у меня есть на данный момент. Есть идеи?
Это выглядит несколько полезным, но мой вопрос касается инкапсуляции запросов, а не запросов. Кроме того, я не получаю доступ к БД за репозиторием, хотя это, вероятно, не имеет значения. – DavidN