Unity

0 views
Skip to first unread message

Laurin Stoll

unread,
Jun 14, 2009, 8:47:59 AM6/14/09
to altnetde
Hallo zusammen,

Ich verkomme ja beinahe zum spammer, aber bitte verzeiht mir, ich habe
gerade die Freude endlich mal auf Unity umzustreigen und einige
Fragen. Abgesehen davon könnt ihr es mir bei der Qualität eurer
Antworten auch nicht übel nehmen, dass ich immer mal wieder frage.
Sozusagen selbstverschuldet ;-)

Folgendes, ich habe drei Fragen zu Unity:

1. Wer darf Unity alles referenzieren?
-------------------------------------------------------------------
Ich habe diverse Komponenten. Jetzt habe ich mich gefragt, seht ihr
die Unity Komponente sozusagen als Milieu-Beziehung? Dürfen alle
Komponenten Unity referenzieren? Oder hat quasi der Einsprungspunkt
Unity referenziert und löst alles auf und gibt das dann per
Constructor Injection an sämtliche Komponenten? Das geht ja
theoretisch...

2. UnityContainer von überall?
------------------------------------------------------------------
Bietet UnityContainer schon irgendwas damit ich von überall an meinen
Standardcontainer komme? Oder macht ihr euch da einfach selbst jeweils
eine Singleton Klasse?

3. Nested Constructor Injection - was geht hier schief?
------------------------------------------------------------------
Stellt euch folgendes Szenario vor:

Es gibt ein Frontend, eine Komponente BusinessLogic und eine
Komponente mit Repositories (natürlich gibts noch Kontrakt-
Komponenten).

Das Frontend arbeitet mit den BL Services über eine Registry:

IModulesRegistry registry = container.Resolve<IModulesRegistry>();

Die Registry erstellt Ihre Services dann per Dependency Attribut:
BL KOMPONENTE:

public class ModulesRegistry : IModulesRegistry
{
[Dependency]
public IUserModule {get; set;}
}

Das UserModule sollte dann auch von Unitry gleich das IUserRepostory
bekommen:

public class UserModule : IUserModule
{
public UserModule(IUserRepository repository)
{ // .... }
}

Und zuletzt dann die Repostories Komponente. UserRepository bekommt
dann den EF Kontext.

public class UserRepository : IUserRepository
{
public UserRepostory(PPEntities context)
{ // .... }
}

So wie ihr seht passiert also eine ziemlich geschachtelte Injection
von Unity. Natürlich ist alles schön in Unity registriert. Beim EF
ObjectContext (PPEntities) habe ich auch schön definiert, dass der
C'tor ohne Argumente genommen werden soll.

So nun zu meinem Problem:
Wenn ich jede Komponente per Unity auflösen lasse zu testzwecken
funktioniert das wunderbar. Lass ich es aber wie oben geschrieben
machen:

IModulesRegistry registry = container.Resolve<IModulesRegistry>();

Dann kriegt Unity diese Schachtelung nicht hin. Nach einigem
Ausprobieren weiss ich dann auch wieso:
Ganz am Ende beim UserRepository welches im C'tor den EF Context
möchte nimmt Unity plötzlich nicht mehr den C'tor ohne Argumente!
Warum nicht?? In der App.config im Frontend ist wunderbar definiert,
dass der C'tor ohne Argumente nehmen soll und das klappt auch wenn ich
dort z.B. ein User Repository auflöse:

IUserRepository rep = container.Resolve<IUserRepository>();

funktioniert wunderbar, da macht er mir einen EF Context und nimmt den
leeren C'tor.

Kann mir das jemand erklären, respk. helfen wie ich Unity sagen kann,
dass er auch am Ende einer solchen Schachtelung noch keinen C'tor mit
Paramentern nehmen soll??
Oder ist das gar nicht gut was ich da mache, von Unity eine solche
Klassenhierarchie erstellen zu lassen?
Sollte ich die Registry besser im Frontend halten und mir per Unity
einzeln die Komponenten holen und dann in der Registry zusammen
schustern? Oder hat Unity am Ende beim erstellen des Repositories die
Konfiguration für den Ctor verloren? Ich verstehe das nicht...

Any help would be very very appreciated :-)

Viele Grüsse
laurin

Sebastian Jancke

unread,
Jun 14, 2009, 10:26:44 AM6/14/09
to altn...@googlegroups.com

Oder macht ihr euch da einfach selbst jeweils
eine Singleton Klasse?
Blos nicht ;-) Dafür gibt es von P&P einen standarisierten Singleton-ServiceLocator. Wenn man sowas braucht, dann lieber diesen nehmen.

-Sebastian

Laurin Stoll

unread,
Jun 15, 2009, 3:11:56 AM6/15/09
to altnetde
Hallo Sebastian,

Danke für deine Antwort. Wieso blos nicht? Ist doch nicht wirklich
einen Unterschied, Unity kann ich problemlos als Service Locator
einsetzen?
Und wieso "wenn man sowas braucht" - initialisierst du deine Container
jedes mal neu?

Hilf mir doch ein wenig auf die Sprünge - und falls du oder jemand
anderes mir zu den anderen Punkten noch einen Anstoss hast/habt, wäre
ich sehr dankbar :) :)

Viele Grüsse und einen guten Start in die Woche euch,

laurin

On 14 Jun., 16:26, Sebastian Jancke <sebastian.jan...@googlemail.com>
wrote:

Mathias Raacke

unread,
Jun 15, 2009, 6:13:38 AM6/15/09
to altnetde
Hallo Laurin,

erstmal vorweg eine super Quelle für Unity und Enterprise Library:
http://www.pnpguidance.net/, das war meine Hauptquelle zu diesem
Thema.

Unity habe ich bisher in einem größeren Projekt (ASP.NET
Intranetanwendung) eingesetzt. Meine Antworten auf Deine Fragen
beziehen sich darauf, wie ich Unity in dem Projekt verwendet habe. Das
ist möglicherweise nicht immer der beste Weg, hat aber prima
funktioniert.

On 14 Jun., 14:47, Laurin Stoll <devc...@yooapps.com> wrote:
> 1. Wer darf Unity alles referenzieren?

In meinem Fall in der Regel nur der "Einsprungspunkt", d.h. bei uns
waren das die Webanwendung und ein Windowsdienst. Von da aus wird
alles über Constructor-Injection aufgebaut.

An einer Stelle gab es zu dieser Regel aber eine Ausnahme, da musste
ich aus der BL .ResolveAll<> aufrufen. Dafür habe ich ein
IContainerAccessor-Interface verwendet, das der BL per Construktor-
Injection übergeben wurde. Wenn ich jetzt so drüber nachdenke hätte
ich aber wohl auch den ResolveAll-Aufruf über ein eigenes Interface
kapseln können und somit ganz auf die Unity-Referenz verzichten
können.

> 2. UnityContainer von überall?

Eigentlich schon unter 1 beantwortet. Würde ich jetzt über ein eigenes
Interface lösen, falls ich es noch einmal implementieren müsste.

Den Container habe ich in einer eigenen HttpApplication-Klasse
erstellt und konfiguriert. Zum größten Teil erfolgt die Konfiguration
über eine Konfigurationsdatei, nur zwei Interfaces die sowieso direkt
von meiner HttpApplication-Klasse implementiert werden sind über Code
konfiguriert. Diese Klasse liegt zusammen mit ein paar anderen
Basisklassen in einem eigenen Projekt, so dass ich sie im nächsten
Projekt, das Unity und das MVP Pattern nutzen soll, einfach
wiederverwenden kann.

Ich hatte auch mal angefangen, darüber zu bloggen, muss aber schon
seit Monaten noch den 2. Teil dazu schreiben ;-)
http://www.outofcoffeeexception.de/2008/10/21/Das+ModelViewPresenter+Pattern+In+ASPNET+Ndash+Teil+1.aspx

Grüße,
Mathias

Ralf Westphal

unread,
Jun 15, 2009, 8:33:52 AM6/15/09
to altnetde
> 1. Wer darf Unity alles referenzieren?
> -------------------------------------------------------------------
> Ich habe diverse Komponenten. Jetzt habe ich mich gefragt, seht ihr
> die Unity Komponente sozusagen als Milieu-Beziehung? Dürfen alle

Unity ist für mich ganz allgemein eine Komponente, die grundsätzliche
alle referenzieren dürften. Ist allgemeine Infrastruktur. (Allerdings
solltest du dann vielleicht lieber global einen Common Service Locator
bei Unity registrieren, der neben deinen eigenen Komponenteninstanzen
injiziert wird. S. http://www.codeplex.com/CommonServiceLocator)

Ansonsten gilt: Eher mit "passiver" DI arbeiten als mit aktiver DL.
Wenn aber DL nötig, dann über einen injizierten DI container, also
kein Singleton.


> ------------------------------------------------------------------
> Bietet UnityContainer schon irgendwas damit ich von überall an meinen
> Standardcontainer komme? Oder macht ihr euch da einfach selbst jeweils
> eine Singleton Klasse?

Nein. Unity bietet das nicht. "Workaround": s.o.


> So nun zu meinem Problem:
> Wenn ich jede Komponente per Unity auflösen lasse zu testzwecken
> funktioniert das wunderbar. Lass ich es aber wie oben geschrieben
> machen:
>
> IModulesRegistry registry = container.Resolve<IModulesRegistry>();
>
> Dann kriegt Unity diese Schachtelung nicht hin. Nach einigem

Keine Ahnung, warum das nicht funktioniert. Ich gehe allerdings auch
anders vor: Ich mache eigentl nur noch imperative Mappings, also nix
XML. Versuche mal, ob das auch für dich einen Unterschied macht. Das
Mapping kann nur einfacher werden ;-) (Hast du in der IModulesRegistry
Impl. den Ctor mit dem passenden Attribut versehen? Auf was anderes
würde ich nicht vertrauen.)

-Ralf

Laurin Stoll

unread,
Jun 15, 2009, 4:57:04 PM6/15/09
to altnetde
Hallo Mathias,

> erstmal vorweg eine super Quelle für Unity und Enterprise Library:http://www.pnpguidance.net/, das war meine Hauptquelle zu diesem
> Thema.

Vielen Dank da scheints wirklich einiges zu geben.

> An einer Stelle gab es zu dieser Regel aber eine Ausnahme, da musste
> ich aus der BL .ResolveAll<> aufrufen. Dafür habe ich ein
> IContainerAccessor-Interface verwendet, das der BL per Construktor-
> Injection übergeben wurde. Wenn ich jetzt so drüber nachdenke hätte
> ich aber wohl auch den ResolveAll-Aufruf über ein eigenes Interface
> kapseln können und somit ganz auf die Unity-Referenz verzichten
> können.

Also quasi ein Service Locator interface?


------------

Hallo Ralf,


> Unity ist für mich ganz allgemein eine Komponente, die grundsätzliche
> alle referenzieren dürften. Ist allgemeine Infrastruktur. (Allerdings
> solltest du dann vielleicht lieber global einen Common Service Locator
> bei Unity registrieren, der neben deinen eigenen Komponenteninstanzen
> injiziert wird. S.http://www.codeplex.com/CommonServiceLocator)

Einfach gesagt: Dabei (also sinn und zweck der sache) geht es einfach
um die Abstrahierung weg von einem bestimmten Container oder
Microkernel oder?

> Ansonsten gilt: Eher mit "passiver" DI arbeiten als mit aktiver DL.
> Wenn aber DL nötig, dann über einen injizierten DI container, also
> kein Singleton.

Wieso nicht? Ich frage einfach mal kritisch, nicht weil ich das gut
oder schlecht finde sondern einfach weil ich noch nicht sehe was dafür
oder dagegen spricht?

> Keine Ahnung, warum das nicht funktioniert. Ich gehe allerdings auch
> anders vor: Ich mache eigentl nur noch imperative Mappings, also nix
> XML. Versuche mal, ob das auch für dich einen Unterschied macht. Das
> Mapping kann nur einfacher werden ;-) (Hast du in der IModulesRegistry
> Impl. den Ctor mit dem passenden Attribut versehen? Auf was anderes
> würde ich nicht vertrauen.)

Ich habe das deklarativ gemacht und dort konfiguriert das er keinen
Ctor nehmen soll. Das klappt beim direkten Auflösen auch wunderbar nur
nested nicht. Hm. Aber du machst das imperativ?? Du deixelst dir das
per FluentApi zusammen? Dann braucht aber ja deine Komponente
referenzen auf sämtliche Contracte und Implementierungen - oder steh
ich grad auf dem Schlauch?
Und wie versehe ich einen EF ObjectContext mit einem
InjectionConstructor Attribute.... ist leider ne generiert Klasse -
dooof!

Vielen Dank euch für euere tatkräftige Unterstützung.

Gruss
Laurin

Alexander Groß

unread,
Jun 15, 2009, 6:00:22 PM6/15/09
to altn...@googlegroups.com
Hi Laurin,

| > Ansonsten gilt: Eher mit "passiver" DI arbeiten als mit aktiver DL.
| > Wenn aber DL nötig, dann über einen injizierten DI container, also
| > kein Singleton.
|
| Wieso nicht? Ich frage einfach mal kritisch, nicht weil ich das gut
| oder schlecht finde sondern einfach weil ich noch nicht sehe was dafür
| oder dagegen spricht?

Gegen einen statischen Gateway zum Container/Singleton spricht z. B. dass du
in Unit Tests IoC intialisieren musst und nicht einfach den Container
stubben bzw. mocken kannst, um den SUTs gewünschte Instanzen
"unterzuschieben".

Beste Grüße,

Alex

Ralf Westphal

unread,
Jun 16, 2009, 8:50:52 AM6/16/09
to altnetde
> > injiziert wird. S.http://www.codeplex.com/CommonServiceLocator)
>
> Einfach gesagt: Dabei (also sinn und zweck der sache) geht es einfach
> um die Abstrahierung weg von einem bestimmten Container oder
> Microkernel oder?

ja. aber es ist nur die beschaffung von instanzen abstrahiert, nicht
der aufbau von mappings.


> Ich habe das deklarativ gemacht und dort konfiguriert das er keinen
> Ctor nehmen soll. Das klappt beim direkten Auflösen auch wunderbar nur
> nested nicht.

eben weil das ein problem macht, einfach mal was anderes probieren.


>Hm. Aber  du machst das imperativ?? Du deixelst dir das
> per FluentApi zusammen? Dann braucht aber ja deine Komponente
> referenzen auf sämtliche Contracte und Implementierungen - oder steh
> ich grad auf dem Schlauch?

nein, nicht jede komponente! das ist der trick. nur eine zentrale
mapping komponente referenziert alle anderen assemblies. im grunde
macht das eine xml-config auch. nur da hast du keine intellisense-
unterstützung. deshalb mache ich es imperativ.

dass eine komponente sooooviele abhängigkeiten hat, macht übrigens
nichts. die abhängigkeiten sind trivial.


> Und wie versehe ich einen EF ObjectContext mit einem
> InjectionConstructor Attribute.... ist leider ne generiert Klasse -
> dooof!

nachträglich kann man imperativ nicht sagen, welcher ctor benutzt
werden soll.
vielleicht ist EF einfach kein so dolles tool? ;-)

-ralf

Laurin Stoll

unread,
Jun 18, 2009, 4:37:12 AM6/18/09
to altnetde
Hallo zusammen,

@Alexander: Ja danke, da hast du natürlich recht. Hm... je mehr testen
umso weniger statisch ^^

@Ralf:

> ja. aber es ist nur die beschaffung von instanzen abstrahiert, nicht
> der aufbau von mappings.

ok.

> nein, nicht jede komponente! das ist der trick. nur eine zentrale
> mapping komponente referenziert alle anderen assemblies. im grunde
> macht das eine xml-config auch. nur da hast du keine intellisense-
> unterstützung. deshalb mache ich es imperativ.
> dass eine komponente sooooviele abhängigkeiten hat, macht übrigens
> nichts. die abhängigkeiten sind trivial.

Ok - und wie sieht so eine Komponente aus?
Ist das irgendwie ein ContainerMapper? Und wie kickst du die an?
Hast du sowas wie ein

IDependencyMapper
{
IUnityContainer Configure();
}

und rufst dann Configure in der Main deines Einsprungspunktes auf?
Kannst du das ein wenig konrketisieren, würde mich interessieren :-)

> nachträglich kann man imperativ nicht sagen, welcher ctor benutzt
> werden soll.

Das stimmt nicht. In der app.config kann ich das sehr wohl. Nur ist es
eben leider fehlerhaft.

> vielleicht ist EF einfach kein so dolles tool? ;-)

Nein - ganz ehrlich es ist bes*****. Microsoft hat da für mein
Verständnis voll am Ziel vorbei geschossen. Aber man hat auch nicht
immer die Wahl!

Naja ich könnte sonst auch noch sowas wie einen IContextAccessor
bauen, der mir den initialisiert. Das würde sonst auch gehen.

Viele Grüsse
Laurin

Steve Wagner

unread,
Jun 18, 2009, 3:55:44 PM6/18/09
to altn...@googlegroups.com
Warum eigentlich Unity? Wie du schon selbst bemerkt hast, ist nicht
alles was Microsoft macht gut. Und Unity ist aus dem ObjectBuilder von
CAB hervorgegangen mit dem ich irgendwie aus Kriegsfuß stehe :-)

Außerdem hab ich in CAB auch die Dependency Attribute hassen gelernt.

-Steve

Laurin Stoll schrieb:

Ralf Westphal

unread,
Jun 20, 2009, 3:19:01 AM6/20/09
to altnetde
> und rufst dann Configure in der Main deines Einsprungspunktes auf?
> Kannst du das ein wenig konrketisieren, würde mich interessieren :-)

ein imperatives mapping ist doch ganz einfach: eine assembly, die alle
anderen referenziert und mit einem DI container deiner wahl mappings
aufbaut.
und am ende erzeugst du dein root objekt und rufst es auf. das kann
auch ein formular sein.
fertig.

es ist wahrscheinlich viel einfacher, als du denkst.

ich mache das z.b. oft in einer winforms EXE ohne formular. die
referenziert kontrakt- und impl-assemblies, baut in Main() die
mappings auf und instanziert über den DI container dann das erste
formular, das ebenfalls referenziert und gemappt wurde.


>
> > nachträglich kann man imperativ nicht sagen, welcher ctor benutzt
> > werden soll.
>
> Das stimmt nicht. In der app.config kann ich das sehr wohl. Nur ist es
> eben leider fehlerhaft.

nein. kann man nicht. weil das eben nicht imperativ ist. das ist
deklarativ.


>
> > vielleicht ist EF einfach kein so dolles tool? ;-)
>
> Nein - ganz ehrlich es ist bes*****. Microsoft hat da für mein
> Verständnis voll am Ziel vorbei geschossen. Aber man hat auch nicht
> immer die Wahl!

hat man nicht? wirklich nicht? dein kunde bestimmt, dass du EF nutzen
musst? interessant

-ralf

Laurin Stoll

unread,
Jun 29, 2009, 12:43:20 PM6/29/09
to altnetde
Hallo Ralf,

Entschuldige die verspätete Antwort - aber besten Dank für deine
zügige!

> ein imperatives mapping ist doch ganz einfach: eine assembly, die alle
> anderen referenziert und mit einem DI container deiner wahl mappings
> aufbaut.
> und am ende erzeugst du dein root objekt und rufst es auf. das kann
> auch ein formular sein.
> fertig.
>
> es ist wahrscheinlich viel einfacher, als du denkst.
>
> ich mache das z.b. oft in einer winforms EXE ohne formular. die
> referenziert kontrakt- und impl-assemblies, baut in Main() die
> mappings auf und instanziert über den DI container dann das erste
> formular, das ebenfalls referenziert und gemappt wurde.

Ja klingt wirklich simpel... da hab ich zu weit gedacht ;-)


> nein. kann man nicht. weil das eben nicht imperativ ist. das ist
> deklarativ.

Ja du hast recht, sry ich habe das Wort "imperativ" übersehen.


> > > vielleicht ist EF einfach kein so dolles tool? ;-)
>
> > Nein - ganz ehrlich es ist bes*****. Microsoft hat da für mein
> > Verständnis voll am Ziel vorbei geschossen. Aber man hat auch nicht
> > immer die Wahl!
>
> hat man nicht? wirklich nicht? dein kunde bestimmt, dass du EF nutzen
> musst? interessant

Ja - auch sowas gibts.... :-( leider

Viele Grüsse
Laurin
Reply all
Reply to author
Forward
0 new messages