На основании информации, представленной здесь, я хотел бы отметить одну или две вещи:
Прежде всего, независимо от того, указаны ли конкретные значения конфигурации во время компоновки или действительно впервые доступны во время выполнения, поскольку пользовательский ввод имеет огромное значение. Пока они могут быть разрешены во время компоновки, все просто, потому что вы можете просто прочитать значения из среды и предоставить их соответствующим конструкторам. Итак, в остальной части этого ответа я собираюсь предположить, что все намного сложнее, и вам действительно нужно получить эти значения от пользователя во время выполнения.
Вместо того, чтобы пытаться придумать API конфигурации общего назначения, я бы предпочел смоделировать то, что на самом деле происходит. В этом случае мне кажется, что мы собираем значения конфигурации от пользователя, так почему бы не смоделировать это явно?
Товарный трейдер
Определите интерфейс следующим образом:
public interface ITradingApiTrader
{
ITradingApi Create(Type apiType);
}
Здесь предполагается, что apiType
может привести к ITradingApi, но компилятор не может принудительно выполнить это. (Причина, по которой я называю это «трейдером», заключается в том, что это разновидность паттерна Product Trader (PLoPD 3).)
Чем это отличается от предыдущего?
Ну, вы можете реализовать метод Create, показывая пользовательский интерфейс для каждого типа ITradingApi. Каждый конкретный пользовательский интерфейс собирает значения, необходимые для его собственной конкретной реализации ITradingApi, и впоследствии возвращает правильно настроенный экземпляр.
Если вы знаете конкретные типы во время компиляции, другие варианты включают в себя:
public interface ITradingApiTrader
{
ITradingApi CreateMT4TradingApi();
ITradingApi CreateFooTradingApi();
ITradingApi CreateBarTradingApi();
// etc.
}
Возможно, вы также можете сделать это (хотя я не пытался это скомпилировать):
public interface ITradingApiTrader
{
ITradingApi Create<T>() where T : ITradingApi;
}
Обратите внимание, что вам не нужно определять первый метод Create ITradingApiTrader, основанный на типе - любой идентификатор (такой как enum или string) мог бы сделать вместо этого.
Посетитель
Если набор ITradingApi (конечный и) известен во время разработки, шаблон проектирования Visitor также может предложить альтернативу.
Если вы используете Visitor, вы можете заставить метод Visit показывать соответствующий пользовательский интерфейс, а затем впоследствии использовать значения, собранные из пользовательского интерфейса, для создания соответствующего экземпляра ITradingApi.
По сути, это всего лишь вариант предыдущего «решения», в котором Product Trader реализован как посетитель.