Unity-Framework DependencyAttribute funktioniert nur für öffentliche Eigenschaften?

8

Ich habe versucht, ein paar Accessibility-Sachen in meinem Code zu bereinigen und habe versehentlich die Unity-Abhängigkeitsinjektion durchbrochen. Nach einer Weile wurde mir klar, dass ich einige öffentliche Eigenschaften markiert hatte, die ich nicht wirklich außerhalb meiner DLLs zu internen angezeigt werden wollte. Dann habe ich angefangen, Ausnahmen zu bekommen.

Offenbar funktioniert das Attribut [Dependency] in Unity nur für öffentliche Eigenschaften. Ich nehme an, das macht Sinn, da die internen und privaten Requisiten für die Unity-Assembly nicht sichtbar sein würden, aber sich wirklich schmutzig anfühlt, um eine Menge öffentlicher Eigenschaften zu haben, die Sie wollen einstellen oder einstellen können, außer Unity.

Gibt es eine Möglichkeit, die Einheit auch interne oder private Eigenschaften festlegen zu lassen?

Hier ist der Komponententest, den ich gerne sehen würde. Derzeit besteht nur der öffentliche Prop-Test:

%Vor%

Aktualisiert:

Ich habe bemerkt, dass der Aufruf-Stack die übergebene Eigenschaft setzt:

%Vor%

Um die interne Version zumindest funktionsfähig zu machen, habe ich sie den Eigenschaften meiner Assembly hinzugefügt:

%Vor%

Allerdings keine Änderung. Unity / ObjectBuilder wird weiterhin die interne Eigenschaft

nicht festlegen     
CodingWithSpike 23.01.2009, 16:36
quelle

8 Antworten

2

Nachdem ich im Reflektor herumgestochert habe, habe ich das herausgefunden. Standardmäßig sucht der Code, der einen Konstruktor für Konstruktorinjektionen findet:

%Vor%

Ohne BindingFlags werden nur öffentliche Konstruktoren erkannt. Mit ein paar Tricksereien (wie beim Kopieren / Einfügen von Reflektoren) können Sie eine UnityContainerExtension erstellen, die dieselben Funktionen wie die Standardimplementierung ausführt, aber den Aufruf von GetConstructors () ändern in:

%Vor%

Fügen Sie dann die Erweiterung in den Einheitscontainer ein. Die implementierte Erweiterung ist ~ 100 Codezeilen, also habe ich sie hier nicht eingefügt. Wenn jemand es will, lass es mich wissen ...

Neuer funktionierender Testfall. Beachten Sie, dass alle von Unity erstellten Klassen jetzt intern sind:

%Vor%

Ich bin sicher, dass ich eine Erweiterung machen kann, um das gleiche zu tun, um nicht-öffentliche Eigenschaften aufzulösen, aber dieser Code war viel komplizierter:)

    
CodingWithSpike 23.01.2009, 18:51
quelle
5

Eine andere Lösung besteht darin, [InjectionMethod] für eine Methode zu verwenden, bei der Sie die Abhängigkeit an die Klasse übergeben.

%Vor%

... usw.

und aufrufend:

%Vor%

wird Init mit der Abhängigkeit von der Einheit aufrufen.

hat das Problem nicht ganz gelöst, ich weiß ... aber

:-) J

    
Johan Leino 17.02.2009 11:16
quelle
5

Wenn die Eigenschaft "get-only" ist, ist es sinnvoller contructor injection zu verwenden als Eigenschaft Injektion.

Wenn Unity die Reflektion verwendet hat, um private oder interne Mitglieder festzulegen, würde dies Sicherheitseinschränkungen für den Codezugriff unterliegen. Insbesondere würde es in einer Umgebung mit wenig Vertrauen nicht funktionieren.

    
Kent Boogaart 23.01.2009 16:50
quelle
3

UPDATE für Enterprise Library 5.0

Da rally52rs möglicherweise gewarnt wird, bricht das Upgrade auf EntLib5.0 seine Implementierung ab. Mit dem gleichen Ansatz wie Rally habe ich über die neue Codebasis nachgedacht und die folgende 5.0-kompatible Version der InternalConstructorSelectorPolicy erstellt.

Beachten Sie, dass sich meine Version speziell auf interne Konstruktoren in der FindLongestConstructor-Methode beschränkt. An diesem Punkt unterscheidet sich mein Code funktional von Rally's .

%Vor%     
Kenneth Baltrinic 09.06.2010 19:19
quelle
2

Die Frage selbst scheint ein Missverständnis zu sein.

Zur Kernaussage:

  

eine Reihe von öffentlichen Eigenschaften, die Sie niemals festlegen oder lassen möchten   in der Lage zu setzen, außer Unity.

Sie möchten sie in Unit-Tests setzen, oder wie würden Sie sonst an Abhängigkeits-Mocks vorbeikommen? Selbst wenn Sie keine Unit-Tests haben, ist es eine seltsame Idee, Abhängigkeiten zu haben, die nichts (außer einer Magie von Unity) einstellen können. Möchten Sie, dass Ihr Code so stark vom Support-Tool abhängt?

Auch öffentliche Eigenschaften sind überhaupt kein Problem, da Ihr Code von Schnittstellen abhängig sein muss, nicht von Implementierungen (einer der SOLID-Prinzipien). Wenn Sie diesem Prinzip nicht folgen, gibt es keinen Grund für Sie, Unity zu verwenden. Sicher würden Sie keine Abhängigkeiten in der Schnittstelle deklarieren, also weiß die konsumierende Klasse nichts über sie.

Ihnen wurde bereits gesagt, dass es besser ist, die Konstruktorinjektion zu verwenden, aber die Injektion von Eigenschaften hat auch ihre Schönheit. Es ermöglicht das Hinzufügen neuer Abhängigkeiten mit weniger Änderungen (insbesondere können Sie bestehende Komponententests nicht ändern, sondern nur neue hinzufügen).

    
Kurtevich 16.10.2012 13:03
quelle
1

@ rally25rs, obwohl der Beitrag mehr als zwei Jahre alt ist, ist er immer noch hoch (views / google etc.), also dachte ich, ich würde meine 2 Cents hinzufügen. Ich hatte das gleiche Problem und entschied mich schließlich für diese Lösung : UnityContainer und interner Konstruktor . Dies ist als Kommentar gedacht, aber ich kann noch keine Kommentare posten.

Sie haben das wahrscheinlich schon gesehen und wissen es immernoch nützlich für jemand anderes, der es ansieht: Das InternalsVisibleTo() -Attribut hätte niemals funktionieren sollen - weil Unity Ihre Klassen nicht direkt aufruft. Stattdessen verwendet es die Reflektion und untersucht Type . Natürlich wird Type nicht geändert, weil das Attribut dort ist. Um die Vorteile von sichtbaren Interna etc. auf der Empfangsseite zu "genießen", müssen Sie explizit den internen c'tor (oder die Eigenschaft) aufrufen.

    
Jonno 30.09.2011 02:12
quelle
0

Basierend auf der Antwort von Kent B habe ich die Konstruktorinjektion geändert, die für öffentliche Klassen funktioniert. Das Root-Problem besteht jedoch immer noch, wenn alles, was Sie jemals zuweisen oder von Unity zugewiesen bekommen möchten, öffentlich sein soll. Dies beinhaltet die Klassen selbst.

Neuer Komponententest:

%Vor%

Mit den Assembly-Attributen:

%Vor%

schlägt mit dem Fehler fehl:

%Vor%

Insgesamt scheint es also so zu sein, dass man, wenn man Unity benutzen will, einfach alles öffentlich markieren muss. Wirklich hässlich für ein Dienstprogramm / eine Bibliothek .dll ...

    
CodingWithSpike 23.01.2009 17:15
quelle
0

Dies ist meine interne Konstruktor-Injektor-Erweiterungsklasse:

Großes potenzielles Problem: 99% davon sind ein Kopieren / Einfügen des Unity-Codes von .NET reflector aus der Unity-Version 4.1.0.0. Neuere Unity-Versionen können die Implementierung ändern, diese Erweiterung unterbrechen oder Flukey-Fehler verursachen. Du bist gewarnt!

%Vor%     
CodingWithSpike 26.06.2009 17:43
quelle

Tags und Links