Re[8]: как ресолвить не передавая ссылки на контейнер ( DI )
От: okon  
Дата: 24.05.18 04:12
Оценка: 5 (1)
Здравствуйте, Sharov, Вы писали:

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




O>>и потом где-то в коде вместо того чтобы делать container.Resolve()



O>>

O>>public class Foo
O>>{
O>>    Foo( Func<MyClass> myClassFactory )
O>>    {
O>>       MyClass instance = myClassFactory();
O>>    }
O>>}

O>>


S>А фабрика-то откуда взялась? Ее же тоже надо resolve'вить. К тому же, мы можем настроить контейнер при создании(resolve)типа использовать фабрику. Т.е. от ссылки на контейнер с последующим resolve мы не ушли.



Она разресолвится автоматом, я же в примере ее зарегистрировал там где региструется все, Foo будет где-то в иерархии и он разресолвится автоматом.

Например самая простая иерархия


public class RootClass
{
    public RootClass( Foo foo )
    {
       ...
    }
}



после создания контейнера вызывается ресолв рута.
Контейнер упоминается только в одном месте в методе CreateContainer и более он не требуется


void CreateContainer()
{

    container.Register<Func<MyClass>>( () => container.Resolve<MyClass>());

     Root = container.Resolve<RootClass>(); 
}
”Жить стало лучше... но противнее. Люди которые ставят точку после слова лучше становятся сторонниками Путина, наши же сторонники делают акцент на слове противнее ( ложь, воровство, лицемерие, вражда )." (с) Борис Немцов
Re[5]: как ресолвить не передавая ссылки на контейнер ( DI )
От: Doc Россия http://andrey.moveax.ru
Дата: 19.05.18 05:52
Оценка: 4 (1)
Здравствуйте, okon, Вы писали:

O>Вот так не хотелось бы делать, т.к. жестко задается имплементация Foo, Bar и сложно для подмены для тех же тестов.


Так и не надо. Фабрика знает конкретные типы (тип) и создает только какую-то свою группу объектов (или один объект). Все они связаны целью, логически и т.д.

Все что надо для создания этой группы — зависимости уже фабрики. И знать эти типы фабрика не должна. Т.е.

public class MyFabric : IMyFabric 
{
    public MyFabric (IFoo foo, IBar bar) { … }

    public ISomething CreateSomething (int i)
    {
         return new Something (i, foo, bar);
         // или например
         // return new Something (foo(i), bar);
    }
}



PS: Кстати, service locator IMHO не всегда антипаттерн. В некоторых случаях он вполне применим. Но, наверное, это тема для отдельного разговора.
Re[3]: как ресолвить не передавая ссылки на контейнер ( DI )
От: Vladek Россия Github
Дата: 26.05.18 11:56
Оценка: 3 (1)
Здравствуйте, okon, Вы писали:

O>Возможно, но пока не понятно как внутри будет выглядеть Factory.CreateSomething, ведь в ней придется либо создавать инстансы вручную, либо как-то ресолвить зависимости.


Не нужно городить огород с фабриками-обёртками над контейнером. Фабрика должна просто создавать экземпляры конкретных классов, передавая им все долгоживущие зависимости через себя. Смысл такой фабрики в том, что она создаётся сразу, держит в себе нужные зависимости, и по запросу создаёт короткоживущие объекты, которым нужны эти зависимости.
Re: как ресолвить не передавая ссылки на контейнер ( DI )
От: Qulac Россия  
Дата: 26.05.18 12:14
Оценка: 3 (1)
Здравствуйте, okon, Вы писали:

O>Пишут что передавать ссылку на IContainer плохо

Под плохо здесь имелось ввиду случай когда класс получает контейнер и сам тянет из него свои зависимости, а не получает их через аргументы конструктора. Если у нас какой-то класс постоянно создаёт какие-то объекты, что часто и бывает, то он зависит от фабрики этих объектов, вот пусть контейнер фабрику ему и передает в качестве зависимости.


P.S. В качестве фабрики, часто передаётся другой экземпляр контейнера "заряженного" под этот класс. Так у нас и все зависимости прописаны в одном месте и класс не сможет насоздавать ни чего лишнего.
Программа – это мысли спрессованные в код
Отредактировано 26.05.2018 13:09 Qulac . Предыдущая версия .
Re: как ресолвить не передавая ссылки на контейнер ( DI )
От: Doc Россия http://andrey.moveax.ru
Дата: 19.05.18 04:41
Оценка: +1
Здравствуйте, okon, Вы писали:

O>Как такие сценарии правильно строятся без передачи и хранения ссылок на контейнеры ?


Задача состоит в создании экземпляра класса так ведь? А подобную задачу решат шаблон Factory.
public class A 
{
    private IMyFactory _myFactory;
    
    public A (IMyFactory myFactory)
    {
        _myFactory = myFactory;
    }


    public IEnumerable<IMyClass> CalculateSomething()
    {
        return Enumerable.Range(1,100).Select( i => _myFactory.CreateSomething(i));
    }
}
Re[6]: как ресолвить не передавая ссылки на контейнер ( DI )
От: okon  
Дата: 23.05.18 10:51
Оценка: +1
Здравствуйте, Sharov, Вы писали:

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


O>>Подразумевается что Resolve делается один раз для корневого объекта, а остальные зависимости сидят в конструкторах и вычисляются автоматом.


S>А почему я не могу для разных объектов,т.е. типов, делать Resolve? Для типа по контейнеру?


Основная идея я так понимаю делать это все при настройке контейнера, в том числе если что-то надо ресолвить когда-то потом, создается функция как-то так


void RegisterTypesInContainer()
{

    ...
    container.Register<Func<MyClass>>( ()=> container.Resolve<MyClass>() );

    ...
}



и потом где-то в коде вместо того чтобы делать container.Resolve()



public class Foo
{
    Foo( Func<MyClass> myClassFactory )
    {
       MyClass instance = myClassFactory();
    }
}



вместо Func<MyClass>() можно делать какие-нибудь IMyClassFactory
”Жить стало лучше... но противнее. Люди которые ставят точку после слова лучше становятся сторонниками Путина, наши же сторонники делают акцент на слове противнее ( ложь, воровство, лицемерие, вражда )." (с) Борис Немцов
как ресолвить не передавая ссылки на контейнер ( DI )
От: okon  
Дата: 19.05.18 04:20
Оценка:
Пишут что передавать ссылку на IContainer плохо,
а как быть если нужно в процессе вычислений создать экземпляр класса и проинициализировать его поля, например с передачей контейнера, например
class A
{
   IContainer container;

   A( IContainer container )
   {
      this.container = container;
   }

   IEnumerable<B> CalculateSomething()
   {
      return Enumerable.Range(1,100).Select( i => container.Resolve<B>(new TypedParameter(type(int), i));
   }
}



Как такие сценарии правильно строятся без передачи и хранения ссылок на контейнеры ?
”Жить стало лучше... но противнее. Люди которые ставят точку после слова лучше становятся сторонниками Путина, наши же сторонники делают акцент на слове противнее ( ложь, воровство, лицемерие, вражда )." (с) Борис Немцов
Re[2]: как ресолвить не передавая ссылки на контейнер ( DI )
От: okon  
Дата: 19.05.18 05:06
Оценка:
Здравствуйте, Doc, Вы писали:

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


O>>Как такие сценарии правильно строятся без передачи и хранения ссылок на контейнеры ?


Doc>Задача состоит в создании экземпляра класса так ведь? А подобную задачу решат шаблон Factory.

Doc>
Doc>public class A 
Doc>{
Doc>    private IMyFactory _myFactory;
    
Doc>    public A (IMyFactory myFactory)
Doc>    {
Doc>        _myFactory = myFactory;
Doc>    }


Doc>    public IEnumerable<IMyClass> CalculateSomething()
Doc>    {
Doc>        return Enumerable.Range(1,100).Select( i => _myFactory.CreateSomething(i));
Doc>    }
Doc>}
Doc>


Возможно, но пока не понятно как внутри будет выглядеть Factory.CreateSomething, ведь в ней придется либо создавать инстансы вручную, либо как-то ресолвить зависимости.

public class MyFactory : IMyFactory
{
    IContainer container;

    public MyFactory(IContainer container)
    {
    this.container = container;
    }
     
    IMyClass CreateSomething(int i)
    {
       return container.Resolve<IMyClass>(new TypedParameter(type(int), i);
    }
}


т.е. пока не ясно как избавиться от container, т.к. конструктор типа имплементирующего IMyClass может принимать массу аргументов которые хотелось бы брать из контейнера а не передавать явно.
”Жить стало лучше... но противнее. Люди которые ставят точку после слова лучше становятся сторонниками Путина, наши же сторонники делают акцент на слове противнее ( ложь, воровство, лицемерие, вражда )." (с) Борис Немцов
Отредактировано 19.05.2018 5:07 okon . Предыдущая версия .
Re[3]: как ресолвить не передавая ссылки на контейнер ( DI )
От: Doc Россия http://andrey.moveax.ru
Дата: 19.05.18 05:22
Оценка:
Здравствуйте, okon, Вы писали:

O>Возможно, но пока не понятно как внутри будет выглядеть Factory.CreateSomething, ведь в ней придется либо создавать инстансы вручную, либо как-то ресолвить зависимости.


Фабрика создает вполне конкретные инстансы вполне конкретных (но только ей известных) типов.
Если надо создавать другие типы — создается другая фабрика.

Если посмотрите внимательно, то реализация Factory уже абстракция и прокинута в класс как интерфейс.
Метод CreateSomething должен возвращать интерфейс ISomething
Собственно больше абстракций / интерфейсов не требуется.
Re[3]: как ресолвить не передавая ссылки на контейнер ( DI )
От: _Raz_  
Дата: 19.05.18 05:26
Оценка:
Здравствуйте, okon, Вы писали:

O>Возможно, но пока не понятно как внутри будет выглядеть Factory.CreateSomething, ведь в ней придется либо создавать инстансы вручную, либо как-то ресолвить зависимости.


    class A
    {
        Func<int, B> bFactory;

        A(Func<int, B> bFactory)
        {
            this.bFactory = bFactory;
        }

        IEnumerable<B> CalculateSomething()
        {
            return Enumerable.Range(1, 100).Select(i => bFactory(i));
        }
    }
    
    //////////////////////////////////
    
    var b = new A(i => container.Resolve<B>(new TypedParameter(typeof(int), i)))
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Re[4]: как ресолвить не передавая ссылки на контейнер ( DI )
От: okon  
Дата: 19.05.18 05:35
Оценка:
_R_>
_R_>    //////////////////////////////////
    
_R_>    var b = new A(i => container.Resolve<B>(new TypedParameter(typeof(int), i)))
    
_R_>


Но ссылку на контейнер так и не понятно где брать, она существует только при ресолве корня и далее ее передавать не рекомендуют.
”Жить стало лучше... но противнее. Люди которые ставят точку после слова лучше становятся сторонниками Путина, наши же сторонники делают акцент на слове противнее ( ложь, воровство, лицемерие, вражда )." (с) Борис Немцов
Re[4]: как ресолвить не передавая ссылки на контейнер ( DI )
От: okon  
Дата: 19.05.18 05:40
Оценка:
Здравствуйте, Doc, Вы писали:

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


O>>Возможно, но пока не понятно как внутри будет выглядеть Factory.CreateSomething, ведь в ней придется либо создавать инстансы вручную, либо как-то ресолвить зависимости.


Doc>Фабрика создает вполне конкретные инстансы вполне конкретных (но только ей известных) типов.

Doc>Если надо создавать другие типы — создается другая фабрика.

Doc>Если посмотрите внимательно, то реализация Factory уже абстракция и прокинута в класс как интерфейс.

Doc>Метод CreateSomething должен возвращать интерфейс ISomething
Doc>Собственно больше абстракций / интерфейсов не требуется.

Имеется ввиду что B может принимать много аргументов конструктора, например

B( int I, IFoo foo, IBar bar )
{
}


В свою очередь Foo : IFoo тоже может иметь сложный конструктор с множеством параметров, через Resolve мы их вычисляем автоматом.

В контейнере мы регистрируем IFoo, IBar а в фабрике как предлагается инстанцировать их ?



Factory
{
  B CreateB( int I )
  {
    return new B(i, new Foo( new X(), new Y() ), new Bar( new Z(), new X() );
  }
}


Вот так не хотелось бы делать, т.к. жестко задается имплементация Foo, Bar и сложно для подмены для тех же тестов.
”Жить стало лучше... но противнее. Люди которые ставят точку после слова лучше становятся сторонниками Путина, наши же сторонники делают акцент на слове противнее ( ложь, воровство, лицемерие, вражда )." (с) Борис Немцов
Re[6]: как ресолвить не передавая ссылки на контейнер ( DI )
От: Doc Россия http://andrey.moveax.ru
Дата: 19.05.18 05:54
Оценка:
Кстати, зависимости же могут передаваться не только через конструктор, но и через свойства и параметры метода.
Поэтому еще есть вариант с

public ISomething CreateSomething (int i,IFoo foo, IBar bar) { … }

а они уже внедряются через конструктор вызывающей стороны
Re: как ресолвить не передавая ссылки на контейнер ( DI )
От: Sharov Россия  
Дата: 20.05.18 10:29
Оценка:
Здравствуйте, okon, Вы писали:

O>Пишут что передавать ссылку на IContainer плохо,


Кто пишет?Чем плохо?
Кодом людям нужно помогать!
Re[2]: как ресолвить не передавая ссылки на контейнер ( DI )
От: okon  
Дата: 20.05.18 22:15
Оценка:
Здравствуйте, Sharov, Вы писали:

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


O>>Пишут что передавать ссылку на IContainer плохо,


S>Кто пишет?Чем плохо?


Кто уже не помню, но смысл был такой что весь граф зависимостей должен определяться в одном месте, а не быть размазан по коду.
”Жить стало лучше... но противнее. Люди которые ставят точку после слова лучше становятся сторонниками Путина, наши же сторонники делают акцент на слове противнее ( ложь, воровство, лицемерие, вражда )." (с) Борис Немцов
Re[3]: как ресолвить не передавая ссылки на контейнер ( DI )
От: Sharov Россия  
Дата: 21.05.18 09:50
Оценка:
Здравствуйте, okon, Вы писали:

O>Кто уже не помню, но смысл был такой что весь граф зависимостей должен определяться в одном месте, а не быть размазан по коду.


Это логично, но ссылку на контейнер надо же передавать, иначе как объекты будут создаваться?
Кодом людям нужно помогать!
Re: как ресолвить не передавая ссылки на контейнер ( DI )
От: GarryIV  
Дата: 21.05.18 11:12
Оценка:
Здравствуйте, okon, Вы писали:

O>Пишут что передавать ссылку на IContainer плохо,

O>а как быть если нужно в процессе вычислений создать экземпляр класса и проинициализировать его поля, например с передачей контейнера, например
O>Как такие сценарии правильно строятся без передачи и хранения ссылок на контейнеры ?

В Спринге это делается как то так


@Bean
public FactoryType factoryType(Dependency1 dep1, Dependency2 dep2) {
  return new FactoryType(dep1, dep2);
}


Тут по сути фабрика которая создает объект типа FactoryType с зависимостями dep1, dep2.

ЗЫЖ Этот метод явно никто не вызывает, он вызывается контейнером и передает туда необходимые зависимости.
WBR, Igor Evgrafov
Отредактировано 21.05.2018 11:14 GarryIV . Предыдущая версия .
Re[4]: как ресолвить не передавая ссылки на контейнер ( DI )
От: okon  
Дата: 21.05.18 16:08
Оценка:
Здравствуйте, Sharov, Вы писали:

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


O>>Кто уже не помню, но смысл был такой что весь граф зависимостей должен определяться в одном месте, а не быть размазан по коду.


S>Это логично, но ссылку на контейнер надо же передавать, иначе как объекты будут создаваться?


Подразумевается что Resolve делается один раз для корневого объекта, а остальные зависимости сидят в конструкторах и вычисляются автоматом.
”Жить стало лучше... но противнее. Люди которые ставят точку после слова лучше становятся сторонниками Путина, наши же сторонники делают акцент на слове противнее ( ложь, воровство, лицемерие, вражда )." (с) Борис Немцов
Re[5]: как ресолвить не передавая ссылки на контейнер ( DI )
От: Sharov Россия  
Дата: 21.05.18 16:39
Оценка:
Здравствуйте, okon, Вы писали:

O>Подразумевается что Resolve делается один раз для корневого объекта, а остальные зависимости сидят в конструкторах и вычисляются автоматом.


А почему я не могу для разных объектов,т.е. типов, делать Resolve? Для типа по контейнеру?
Кодом людям нужно помогать!
Re[7]: как ресолвить не передавая ссылки на контейнер ( DI )
От: Sharov Россия  
Дата: 23.05.18 13:35
Оценка:
Здравствуйте, okon, Вы писали:



O>и потом где-то в коде вместо того чтобы делать container.Resolve()



O>

O>public class Foo
O>{
O>    Foo( Func<MyClass> myClassFactory )
O>    {
O>       MyClass instance = myClassFactory();
O>    }
O>}

O>


А фабрика-то откуда взялась? Ее же тоже надо resolve'вить. К тому же, мы можем настроить контейнер при создании(resolve)типа использовать фабрику. Т.е. от ссылки на контейнер с последующим resolve мы не ушли.
Кодом людям нужно помогать!
Re[9]: как ресолвить не передавая ссылки на контейнер ( DI )
От: Sharov Россия  
Дата: 24.05.18 11:02
Оценка:
Здравствуйте, okon, Вы писали:

O>после создания контейнера вызывается ресолв рута.

O>Контейнер упоминается только в одном месте в методе CreateContainer и более он не требуется

O>
O>void CreateContainer()
O>{

O>    container.Register<Func<MyClass>>( () => container.Resolve<MyClass>());

O>     Root = container.Resolve<RootClass>(); 
O>}

O>


Он будет упоминаться в каждом классе, где как минимум требуется RootClass или еще чего. Т.е. опять же, его всюду придется инжектить, хотя бы через конструктор класса, там же, в конструкторе, получить от него
все необходимое и забыть про него.
Кодом людям нужно помогать!
Re[6]: как ресолвить не передавая ссылки на контейнер ( DI )
От: Jericho113 Украина  
Дата: 24.05.18 11:29
Оценка:
Здравствуйте, Doc, Вы писали:

Doc>PS: Кстати, service locator IMHO не всегда антипаттерн. В некоторых случаях он вполне применим. Но, наверное, это тема для отдельного разговора.

А подскажите в каких случаях применение сервис локатора оправдано?
Мне из моего опыта работы только 1 раз приходилось с этим сталкиваться когда под SharePoint писал — но там по другому вообще невозможно было.

Есть ли еще какие либо практические случаи оправданного применения сервис локатора
NetDigitally yours ....
Отредактировано 24.05.2018 11:30 Jericho113 . Предыдущая версия .
Re[10]: как ресолвить не передавая ссылки на контейнер ( DI
От: okon  
Дата: 24.05.18 11:53
Оценка:
Здравствуйте, Sharov, Вы писали:

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


O>>после создания контейнера вызывается ресолв рута.

O>>Контейнер упоминается только в одном месте в методе CreateContainer и более он не требуется

O>>
O>>void CreateContainer()
O>>{

O>>    container.Register<Func<MyClass>>( () => container.Resolve<MyClass>());

O>>     Root = container.Resolve<RootClass>(); 
O>>}

O>>


S>Он будет упоминаться в каждом классе, где как минимум требуется RootClass или еще чего. Т.е. опять же, его всюду придется инжектить, хотя бы через конструктор класса, там же, в конструкторе, получить от него

S>все необходимое и забыть про него.

Для RootClass не совсем я понял, например если нам нужен RootClass где-то внутри мы просто укажем его в конструкторе
Вот например, все разресолвится без передачи контейнера


public class RootClass
{


   RootClass( Foo foo)
   {

   }
}

public class MyClass
{
   public MyClass( RootClass root)   
   {
   }
}


public class Foo
{
    Foo( Func<MyClass> myClassFactory)
    {
    var myClass = myClassFactory();
    }
}
”Жить стало лучше... но противнее. Люди которые ставят точку после слова лучше становятся сторонниками Путина, наши же сторонники делают акцент на слове противнее ( ложь, воровство, лицемерие, вражда )." (с) Борис Немцов
Отредактировано 24.05.2018 11:55 okon . Предыдущая версия .
Re: как ресолвить не передавая ссылки на контейнер ( DI )
От: 0x7be СССР  
Дата: 29.05.18 09:13
Оценка:
Здравствуйте, okon, Вы писали:

O>Пишут что передавать ссылку на IContainer плохо,

O>а как быть если нужно в процессе вычислений создать экземпляр класса и проинициализировать его поля, например с передачей контейнера, например
O>Как такие сценарии правильно строятся без передачи и хранения ссылок на контейнеры ?
class a
{
    private Func<B> _getB;

    public A(Func<B> getB)
    {
    }

    IEnumerable<B> CalculateSomething()
    {
        return Enumerable.Range(1,100).Select( i => _getB());
    }
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.