Borysław B.

Borysław B. Mgr inżynier
informatyki,
właściciel Matrix
Reliability

Temat: ASP.NET MVC: Ninject a wstrzykiwanie NIE do kontrolerów

Cześć,

Przepraszam jeśli głupio to zabrzmi, ale trochę się zgubiłem w Dependency Injection.

Standardowo dziedziczenie naszej MvcApplication po NinjectHttpApplication i przeładowanie OnApplicationStarted i CreateKernel będzie skutkowało automatycznym wstrzykiwaniem zależności do kontrolerów.

Da się użyć tego mechanizmu, by wstrzykiwało mi zależności do dowolnych klas, gdy zawołam sobie w dowolnym miejscu pusty konstruktor klasy?


ISomeClass someClass = new SomeClass();



public SomeClass : ISomeClass
{
public SomeClass(IFormsAuthenticationService formsAuthenticationService, IMembershipService accountMembershipService)
{
FormsService = formsAuthenticationService;
MembershipService = accountMembershipService;
}

public SomeClass()
{

}

internal IFormsAuthenticationService FormsService { get; set; }
internal IMembershipService MembershipService { get; set;
}

konto usunięte

Temat: ASP.NET MVC: Ninject a wstrzykiwanie NIE do kontrolerów

Da się użyć tego mechanizmu, by wstrzykiwało mi zależności do dowolnych klas, gdy zawołam sobie w dowolnym miejscu pusty konstruktor klasy?
ISomeClass someClass = new SomeClass();
Nie znam się na Ninject, ale to co napisałeś - użycie konstruktora - jest wbrew DI! To jest odpowiedzialność containera aby odpowiednio konstruować obiekty, Ty nie musisz wiedzieć, czy to konstruktor, factoria lub inny creational pattern.

Generalnie w application root (MvcApplication OnStart) konstruujesz i konfigurujesz container (często jest to zautomatyzowane). Zapewni on, że kontrolery będą stworzone z odpowiednimi zależnościami i tak powinieneś postępować.

Jeżeli chcesz stworzyć jakiś obiekt, którego czas życia ma być krótszy od kontrolera, to ja tego unikam, ale jak muszę to biorę container (gdzieś go muszę przechować) i explicite resolvuję daną instancję.
Idealnie w aplikacji webowej w ogóle containera nie powinno się używać explicite - oczywiście moim zdaniem:)
Jacek R.

Jacek R. programista

Temat: ASP.NET MVC: Ninject a wstrzykiwanie NIE do kontrolerów

To się nie może zrobić samo, jak nazwa wskazuje, musi być możliwość wstrzyknięcia zależności do Twojego obiektu z zewnątrz. Najpopularniejsze jest wstrzykiwanie właśnie przez konstruktor i tego powinieneś się trzymać (można wstrzykiwać też przez metody, ale tego głównie używa się wtedy, kiedy obiekt masz już gotowy i/lub nie możesz nadpisać konstruktora).

Konstruktor z parametrami, który napisałeś, jest tutaj na miejscu. Teraz musisz zbindować odpowiednie klasy w ninject:
Bind<IFormsAuthenticationService>().To<FormsService>();
Bind<IMembershipService>().To<MembershipService>();
No i potem, żeby wstrzyknięcie było automatyczne (bo możesz to i ręcznie zrobić używając konstruktora), pobierasz obiekt np w ten sposób:
IKernel kernel = new StandardKernel();
ISomeClass someClass = kernel.Get<SomeClass>();

Jak napisał Maciek, korzystając z DI nie używa się konstruktorów w zasadzie :)
Borysław B.

Borysław B. Mgr inżynier
informatyki,
właściciel Matrix
Reliability

Temat: ASP.NET MVC: Ninject a wstrzykiwanie NIE do kontrolerów

Jacek Romanowski:
Konstruktor z parametrami, który napisałeś, jest tutaj na miejscu. Teraz musisz zbindować odpowiednie klasy w ninject:
Bind<IFormsAuthenticationService>().To<FormsService>();
Bind<IMembershipService>().To<MembershipService>();
No i potem, żeby wstrzyknięcie było automatyczne (bo możesz to i ręcznie zrobić używając konstruktora), pobierasz obiekt np w ten sposób:
IKernel kernel = new StandardKernel();
ISomeClass someClass = kernel.Get<SomeClass>();

Zrobiłem bindowania w ServiceModule, wziąłem SomeClass za pomocą kernela, ale nie wsrzyknęło się nic. Coś jeszcze należy robić ?
Tomasz M.

Tomasz M. never go full
retard!

Temat: ASP.NET MVC: Ninject a wstrzykiwanie NIE do kontrolerów

Ale jak tworzysz binding to musisz użyc konkretnego konstruktora chyba (nie wiem, bo używam Autofaca, Ninjecta raz chyba użyłem). Poza tym chyba powinieneś użyć atrybutu [Inject] przy properties, a i properties muszą być chyba publiczne (ale to mówię na podstawie krótkiego doświadczenia w Ninject).


public class Sale3
{
private readonly ITaxCalculator taxCalculator;

public Sale3() { }

[Inject]
public Sale3(ITaxCalculator taxCalculator)
{
this.taxCalculator = taxCalculator;
}

// OTHER STUFF
}


Za http://stefanoricciardi.com/2011/02/04/ninject-mini-tu...Tomasz M. edytował(a) ten post dnia 10.05.12 o godzinie 13:54
Jacek R.

Jacek R. programista

Temat: ASP.NET MVC: Ninject a wstrzykiwanie NIE do kontrolerów

To zależy wszystko od kontekstu w jakim jesteś. Zbinduj to sobie do tego samego kernela i sprawdź czy Ci działa.

IKernel kernel = new StandardKernel();
kernel.Bind<IFormsAuthenticationService>().To<FormsService>();
kernel.Bind<IMembershipService>().To<MembershipService>();
ISomeClass someClass = kernel.Get<SomeClass>();


Atrybut [Inject] nie jest konieczny, to jest jeden ze sposobów pracy, ale nie trzeba z tego korzystać.

Tutaj masz prosty tutorial, zaczynający od podstaw https://github.com/ninject/ninject/wiki/Dependency-Inje...
Borysław B.

Borysław B. Mgr inżynier
informatyki,
właściciel Matrix
Reliability

Temat: ASP.NET MVC: Ninject a wstrzykiwanie NIE do kontrolerów

Jacek Romanowski:
Tutaj masz prosty tutorial, zaczynający od podstaw

Wielkie dzięki, teraz rozumiem
Borysław B.

Borysław B. Mgr inżynier
informatyki,
właściciel Matrix
Reliability

Temat: ASP.NET MVC: Ninject a wstrzykiwanie NIE do kontrolerów

Mam jeszcze pytanie. Jak rozwiązać taką sytuację:

Chcę wstrzyknąć w konstruktor dwa obiekty a trzeci chcę przekazać przez referencję (nie chcę by Ninject go tworzył)

Powiedzmy coś takiego:


public SomeClass(IFormsAuthenticationService formsAcc, IMembershipService membServ, ObjectContext objectContext);


da się to jakoś zrobić np. przy użyciu WithConstructorArgument? - bo nie znalazłem takiego przykładu?Borysław Bobulski edytował(a) ten post dnia 16.05.12 o godzinie 12:58

konto usunięte

Temat: ASP.NET MVC: Ninject a wstrzykiwanie NIE do kontrolerów

Borysław Bobulski:
Chcę wstrzyknąć w konstruktor dwa obiekty a trzeci chcę przekazać przez referencję
Chcesz wstrzyknąć trzy obiekty. I kropka.

Natomiast pierwsze dwa mają mieć inny cykl życia (per resolve) niż ten ostatni (singleton), ale to jest kwestia konfiguracji containera.

Sam ObjectContext nie jest żadną abstrakcją - na odległość śmierdzi EF; opakuj to w jakieś repozytorium i niech implementacja tegoż repozytorium tworzy i niszczy instancję ObjectContext.

EF w wersji CodeFirst umożliwia abstrahowanie od ObjectContext; oczywiści w runtime on tam zawsze istnieje, ale nie pojawia się w publicznym interfejsie.
Jacek R.

Jacek R. programista

Temat: ASP.NET MVC: Ninject a wstrzykiwanie NIE do kontrolerów

Borysław Bobulski:
Mam jeszcze pytanie. Jak rozwiązać taką sytuację:

Chcę wstrzyknąć w konstruktor dwa obiekty a trzeci chcę przekazać przez referencję (nie chcę by Ninject go tworzył)


public SomeClass(IFormsAuthenticationService formsAcc, IMembershipService membServ, ObjectContext objectContext);
W podanym kodzie nie przekazujesz przez referencję. Prawdopodobnie źle używasz tego pojęcia, więc krótko wytłumaczę, że jest różnica, bo w C# przekazywanie przez referencję wymaga słówka ref lub out. To co zaprezentowałeś, to standardowe przekazanie referencji przez wartość :)

Więcej info na ten (poboczny, sorki) temat: http://msdn.microsoft.com/en-us/library/14akc2c7.aspx

Następna dyskusja:

Logowanie w ASP.NET MVC 3 +...




Wyślij zaproszenie do