Фабрика в приложении, использующем IoC
От: Poul_Ko Казахстан  
Дата: 05.09.11 03:21
Оценка:
Привет всем.

Имеется .NET приложение, использующее Unity. Возникла необходимость в фабрике объектов — что-то вроде "Абстрактной фабрики" в терминологии GoF.
Конструкторы объектов, которые должна создавать фабрика, можно разделить на категории:
1) "глобальные" сервисы, доступны через IoC-контейнер
2) конфигурационные параметры, их значения определяются при создании фабрики и не должны быть видимы использующему фабрику коду
3) параметры, указываемые при создании объекта, должны быть переданы в метод фабрики

Как реализовать подобную фабрику?
Возможно, у данной задачи есть другое решение?


Покажу псевдокодом.
// Интерфейс фабрики
public interface IFactory<T>
{
  // Методы для создания и конфигурирования фабрики
}


// Пример объекта, который должна создавать фабрика
public sealed class Foo : IFoo
{
  public Foo(
    IService service,    // Значение этого параметра нужно получать из Unity
    String param,        // Значение этого параметра узнаём при конфигурации фабрики
    Context context)     // Значение этого параметра становится известно только перед созданием объекта
  {
  ...
  }
}


// Использование фабрики, в каком-либо классе
public class Bar
{
  public IFactory<IFoo> Factory {get; set};

  public void SomeMethod()
  {
    Context fooContext = ...;           // Значение третьего параметра

    IFoo foo = this.fooFactory.?????    // Код создания объекта
    ...
  }
}


// Создание и конфигурирование фабрики, при запуске приложения
String paramValue = ...;                           // Значение второго параметра

Factory<IFoo> factory = new Factory<IFoo>(???);    // Код создания и
???????                                            // конфигурирования фабрики

Bar bar = ...;
bar.FooFactory = factory;
Brainbench transcript #6370594
Re: Фабрика в приложении, использующем IoC
От: Аноним  
Дата: 05.09.11 04:42
Оценка:
Здравствуйте, Poul_Ko, Вы писали:

P_K>Привет всем.


P_K>Как реализовать подобную фабрику?

P_K>Возможно, у данной задачи есть другое решение?
посмотрите на наследников InjectionMember
Один из них вам должен подойти (InjectionFactory или InjectionConstructor)
Re: Фабрика в приложении, использующем IoC
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 05.09.11 06:29
Оценка:
Здравствуйте, Poul_Ko, Вы писали:

P_K>Привет всем.


P_K>Имеется .NET приложение, использующее Unity. Возникла необходимость в фабрике объектов — что-то вроде "Абстрактной фабрики" в терминологии GoF.

P_K>Конструкторы объектов, которые должна создавать фабрика, можно разделить на категории:
P_K>1) "глобальные" сервисы, доступны через IoC-контейнер
P_K>2) конфигурационные параметры, их значения определяются при создании фабрики и не должны быть видимы использующему фабрику коду
P_K>3) параметры, указываемые при создании объекта, должны быть переданы в метод фабрики

P_K>Как реализовать подобную фабрику?

P_K>Возможно, у данной задачи есть другое решение?

А для чего тебе это все нужно?
Re[2]: Фабрика в приложении, использующем IoC
От: Poul_Ko Казахстан  
Дата: 05.09.11 08:35
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Здравствуйте, Poul_Ko, Вы писали:


P_K>>Привет всем.


P_K>>Имеется .NET приложение, использующее Unity. Возникла необходимость в фабрике объектов — что-то вроде "Абстрактной фабрики" в терминологии GoF.

P_K>>Конструкторы объектов, которые должна создавать фабрика, можно разделить на категории:
P_K>>1) "глобальные" сервисы, доступны через IoC-контейнер
P_K>>2) конфигурационные параметры, их значения определяются при создании фабрики и не должны быть видимы использующему фабрику коду
P_K>>3) параметры, указываемые при создании объекта, должны быть переданы в метод фабрики

P_K>>Как реализовать подобную фабрику?

P_K>>Возможно, у данной задачи есть другое решение?

G>А для чего тебе это все нужно?


Я описал задачу абстрактно потому, что она встречается в нескольких местах. Везде суть одна — нужно создавать объекты, параметры создания которых могут определяться глобально, конфигурацией и контекстом использования.

Давайте возьмём конкретную ситуацию. Пусть разрабатывается "богатое" клиентское приложение на WinForms. Одной из важных частей функциональности является табличное отображение данных. Пусть за отображение данных в одном столбце грида отвечает интерфейс IColumnController.

Тогда модуль, который отображает данные в табличном виде, среди прочего должен оперировать экземплярами IColumnController. Идея в том, чтобы передать в этот модуль при его конфигурировании набор фабрик IColumnController'ов (по одной на каждый столбец). В нужное время модуль создаст объекты IColumnController через переданные фабрики.

Конкретные классы, реализующие IColumnController, могут зависеть от каких угодно сервисов, имеющихся в приложении, в том числе и не существующих на момент проектирования. Эти зависимости логично разрешать через Unity. Примером конфигурационной информации для ColumnController может быть формат вывода значения (не имеет смысла делать отдельный класс под каждый формат, проще передать в экземпляр строку формата).
Brainbench transcript #6370594
Re[3]: Фабрика в приложении, использующем IoC
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 05.09.11 08:51
Оценка:
Здравствуйте, Poul_Ko, Вы писали:

P_K>Здравствуйте, gandjustas, Вы писали:


G>>Здравствуйте, Poul_Ko, Вы писали:


P_K>>>Привет всем.


P_K>>>Имеется .NET приложение, использующее Unity. Возникла необходимость в фабрике объектов — что-то вроде "Абстрактной фабрики" в терминологии GoF.

P_K>>>Конструкторы объектов, которые должна создавать фабрика, можно разделить на категории:
P_K>>>1) "глобальные" сервисы, доступны через IoC-контейнер
P_K>>>2) конфигурационные параметры, их значения определяются при создании фабрики и не должны быть видимы использующему фабрику коду
P_K>>>3) параметры, указываемые при создании объекта, должны быть переданы в метод фабрики

P_K>>>Как реализовать подобную фабрику?

P_K>>>Возможно, у данной задачи есть другое решение?

G>>А для чего тебе это все нужно?


P_K>Я описал задачу абстрактно потому, что она встречается в нескольких местах. Везде суть одна — нужно создавать объекты, параметры создания которых могут определяться глобально, конфигурацией и контекстом использования.


Параметры можно помещать в сам контейнер, для контекста использования создавать дочерние контейнеры. Кроме того можно тупо возвращать функции + factory расширение, которое позволит генерировать функцию нужного вида.
Re[4]: Фабрика в приложении, использующем IoC
От: Poul_Ko Казахстан  
Дата: 05.09.11 09:10
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Параметры можно помещать в сам контейнер, для контекста использования создавать дочерние контейнеры. Кроме того можно тупо возвращать функции + factory расширение, которое позволит генерировать функцию нужного вида.


Это и было моей первой реализацией.
Напрягает то, что при помещении параметра в контейнер не проверяется, имеет ли конструктор класса такой параметр. Получается, что пока мы не попытаемся создать объект мы не узнаем, что параметр был задан неправильно (или не задан, или значение имеет неподходящий тип...). Хотелось бы такие ошибки отлавливать, например, при регистрации типа.
Brainbench transcript #6370594
Re[5]: Фабрика в приложении, использующем IoC
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 05.09.11 10:45
Оценка:
Здравствуйте, Poul_Ko, Вы писали:

P_K>Здравствуйте, gandjustas, Вы писали:


G>>Параметры можно помещать в сам контейнер, для контекста использования создавать дочерние контейнеры. Кроме того можно тупо возвращать функции + factory расширение, которое позволит генерировать функцию нужного вида.


P_K>Это и было моей первой реализацией.

P_K>Напрягает то, что при помещении параметра в контейнер не проверяется, имеет ли конструктор класса такой параметр. Получается, что пока мы не попытаемся создать объект мы не узнаем, что параметр был задан неправильно (или не задан, или значение имеет неподходящий тип...). Хотелось бы такие ошибки отлавливать, например, при регистрации типа.

Сделай надстройку над контейнером, валидирующую параметры. Будет что-то вроде

var childContainer = baseContainer.InitilizeContext(parameters);


Где InitilizeContext — экстеншн.
Re[6]: Фабрика в приложении, использующем IoC
От: Poul_Ko Казахстан  
Дата: 06.09.11 02:41
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Сделай надстройку над контейнером, валидирующую параметры. Будет что-то вроде


Спасибо, поизучаю вопрос в этом направлении.
Сейчас остановился на использовании Resolve(Type, ResolverOverride[]), это не требует создания дочернего контейнера.

Вообще, меня больше интересует как подобные архитектурные проблемы решают другие разработчики. Возможно как-то можно обойтись без фабрик? Создавать все объекты заранее и хранить уже созданные? Использовать service lookup? Какие ещё есть варианты?
Brainbench transcript #6370594
Re[7]: Фабрика в приложении, использующем IoC
От: . Великобритания  
Дата: 09.09.11 14:25
Оценка:
Здравствуйте, Poul_Ko, Вы писали:

P_K>Какие ещё есть варианты?

Вроде что-то похожее есть в Guice.
Как я понял, получится что-то типа этого:

Твои интерфейсы и имплементация:
public interface IFoo
{
...
}
public interface IFooFactory
{
 IFoo create(Context context);
}

public class Foo : IFoo
{
 @Inject
 Foo(
  IService service,
  String param,
  ... // можно сколь угодно много разных зависимостей добавить.
  @Assisted Context context) // @Assisted параметры должны соотвествовать методу create фабрики, можно делать несколько.
 {
   ...
 }
}

конфигурирование модуля:
install(new FactoryModuleBuilder()
     .implement(IFoo.class, Foo.class)
     .build(IFooFactory.class));

используем:
IFooFactory fooFactory = injector.getInstance(IFooFactory.class);
IFoo foo = fooFactory.create(new MyCoolContext());

Всё, остальное работает автомагически.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.