Информация об изменениях

Сообщение Re[5]: Как наиболее корректно работать с глобальными данными от 03.07.2015 23:42

Изменено 03.07.2015 23:44 Evgeny.Panasyuk

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

A>а вообще если использовать что-то типа DI-контейнера/сервис-локатора, то код получается довольно простым.

A>
A>using MyDIContainer = std::tuple<Logger*, Config*, ...>;

A>class Foo {
A>public:
A>  Foo(const MyDIContainer& di_container) {
A>    auto cfg = get<Config*>(di_container); // std::get
A>    ...
A>    log(di_container, "something", 123); // calls "if (auto logger = get<Logger*>(di_container)) logger->log(args...);"
A>    ...
A>    auto bar = allocate<Bar>(di_container, 456); // calls "get<Allocator*>(di_container)->Create<T>(args...);"
A>  };
A>};
A>


У тебя здесь обычный внешний параметр, пусть и составной.

IoC/DI-контейнер же это некоторый объект, как правило глобальный, который умеет создавать объекты требующие зависимости. Сами зависимые классы его не видят, и о нём ничего не знают.
Конкретные зависимости выбираются в соответствии с настроенными правилами — например можно указать что объекту Bar всегда давать логгер типа LoggerBar, или например внутри каждого потока (или даже соединения) использовать отдельный логгер.

Вот первый попавшийся пример:
public interface IWeapon  
{  
    void sord();  
}  

public class Ninja : IWeapon  
{  
    public void sord()  
    {  
        Console.WriteLine("I am using Sord");  
    }  
}  

public class sourav  
{  
    IWeapon ObjWeapon = null;  
    public sourav(IWeapon tmpWeapon)  
    {  
        this.ObjWeapon = tmpWeapon;  
    }  

    public void Attack()  
    {  
        this.ObjWeapon.sord();  
    }  
}  

class Program  
{  
    static void Main(string[] args)  
    {  
        Ninject.IKernel kernal = new StandardKernel();  
        kernal.Bind<IWeapon>().To<Ninja>();  
        var instance = kernal.Get<sourav>();  
        instance.Attack();   
        Console.ReadLine();  
    }  
}
Re[5]: Как наиболее корректно работать с глобальными данными
Здравствуйте, Abyx, Вы писали:

A>а вообще если использовать что-то типа DI-контейнера/сервис-локатора, то код получается довольно простым.

A>
A>using MyDIContainer = std::tuple<Logger*, Config*, ...>;

A>class Foo {
A>public:
A>  Foo(const MyDIContainer& di_container) {
A>    auto cfg = get<Config*>(di_container); // std::get
A>    ...
A>    log(di_container, "something", 123); // calls "if (auto logger = get<Logger*>(di_container)) logger->log(args...);"
A>    ...
A>    auto bar = allocate<Bar>(di_container, 456); // calls "get<Allocator*>(di_container)->Create<T>(args...);"
A>  };
A>};
A>


У тебя здесь обычный внешний параметр, пусть и составной.

IoC/DI-контейнер же это некоторый объект, как правило глобальный, который умеет создавать объекты требующие зависимости. Сами зависимые классы его не видят, и о нём ничего не знают.
Конкретные зависимости выбираются в соответствии с настроенными правилами — например можно указать что объекту Bar всегда давать логгер типа LoggerBar, или например внутри каждого потока (или даже соединения) использовать отдельный логгер.

Вот первый попавшийся пример (с кучей опечаток ):
public interface IWeapon  
{  
    void sord();  
}  

public class Ninja : IWeapon  
{  
    public void sord()  
    {  
        Console.WriteLine("I am using Sord");  
    }  
}  

public class sourav  
{  
    IWeapon ObjWeapon = null;  
    public sourav(IWeapon tmpWeapon)  
    {  
        this.ObjWeapon = tmpWeapon;  
    }  

    public void Attack()  
    {  
        this.ObjWeapon.sord();  
    }  
}  

class Program  
{  
    static void Main(string[] args)  
    {  
        Ninject.IKernel kernal = new StandardKernel();  
        kernal.Bind<IWeapon>().To<Ninja>();  
        var instance = kernal.Get<sourav>();  
        instance.Attack();   
        Console.ReadLine();  
    }  
}