2009-07-09 20 views
9

Ich weiß, dass einige DI-Frameworks dies unterstützen (z. B. Ninject), aber ich möchte speziell wissen, ob es mit möglich ist.Kann Autofac automatisch selbstbindend?

Ich möchte in der Lage sein, einen Autofac-Container nach einer konkreten Klasse zu fragen und eine Instanz mit allen passenden Konstruktorabhängigkeiten zurückzusenden, , ohne jemals diese konkrete Klasse zu registrieren. Das heißt, wenn ich es nie explizit binden, dann automatisch die konkrete Klasse an sich binden, als ob ich builder.Register<MyClass>();

Ein gutes Beispiel genannt hatte, als dies nützlich wäre, ist Viewmodels. In MVVM ist die Schichtung so, dass nur die Ansicht vom ViewModel abhängt, und das über eine lose Typisierung, und Sie testen die Ansicht trotzdem nicht in der Einheit. Es ist also nicht nötig, das ViewModel für Tests zu verspotten - und daher gibt es keinen Grund, für jedes ViewModel eine Schnittstelle zu haben. In diesem Fall ist das übliche DI-Muster von "register this interface to resolve to this class" unnötige Komplexität. Explizit selbstbindend, wie builder.Register<MyClass>();, fühlt sich auch wie ein unnötiger Schritt an, wenn es um etwas so Einfaches wie eine konkrete Klasse geht.

Ich kenne die reflection-based registration example in den Autofac-Dokumenten, aber das ist auch nicht nach meinem Geschmack. Ich möchte nicht die Komplexität (und Langsamkeit) der Registrierung aller möglichen Klassen im Voraus; Ich möchte, dass der Rahmen mir gibt, was ich brauche, wenn ich es brauche. Konvention über Konfiguration und all das.

Gibt es eine Möglichkeit, Autofac so zu konfigurieren, dass es sagen kann "Oh, das ist ein konkreter Typ, und niemand hat es registriert, also werde ich einfach so handeln, als wäre es mit den Standardeinstellungen registriert worden"?

Antwort

12
builder.RegisterTypesMatching(type => type.IsClass) 

Wenn Sie look at the source Sie werden sehen, dass RegisterTypesMatching (und RegisterTypesFromAssembly) wird jegliche Reflexion nicht zu tun. Alles Autofac macht in diesem Fall eine Regel, die einen Typ akzeptiert oder nicht. In meinem obigen Beispiel akzeptiere ich jeden Typ, der eine Klasse ist.

Im Fall von RegisterTypesFromAssembly registriert Autofac eine Regel, die besagt: "Wenn der Typ, den Sie zu lösen versuchen, Assembly == die angegebene Assembly hat, dann gebe ich Ihnen eine Instanz".

So:

  1. keine Art Reflexion an Registerzeit erfolgt
  2. jeden Typ, der die Kriterien erfüllt wird gelöst werden

die konkreten Typen direkt registrieren Vergleich, wird dies Haben Sie einen Perf Treffer zur Zeit der Auflösung, da Autofac zB herausfinden muss Konstruktor Anforderungen. Wenn Sie jedoch mit dem standardmäßigen Instanzbereich (Singleton) fortfahren, nehmen Sie den Treffer nur beim ersten Mal, wenn Sie diesen Typ auflösen. Beim nächsten Mal wird die bereits erstellte Singleton-Instanz verwendet.

Update: in Autofac 2 gibt es eine bessere Möglichkeit, den Container in der Lage, alles zu lösen. Dies beinhaltet the AnyConcreteTypeNotAlreadyRegistered registration source.

+0

Sweet - klingt genau nach dem was ich gesucht habe. Vielen Dank! –

2

was:

builder.RegisterTypesFromAssembly(Assembly.GetExecutingAssembly()); 

keine Reflexion erfolgt, wie Peter Lillevold points out.

+1

Meine vorherigen Kommentare entfernt, weil Sie Recht hatten (wie Sie in Ihrer Bearbeitung geklärt haben): RegisterTypesFromAssembly führt keine Massenreflexion durch, wie der Name vermuten lässt. Es gehört zu einer Familie von Shorthand-Funktionen rund um RegisterTypesMatching und macht genau das, wonach ich suche, aber mit viel feinerer Kontrolle, was ziemlich süß ist. Ich entschuldige mich dafür, dass Sie Ihre Antwort beim ersten Mal falsch verstanden haben. –

+0

Der Link, den Sie gaben, ist gebrochen ... – Guillaume

+1

bitte verzeihen Sie mir, aber diese Antwort ist 3 Jahre alt: P außerdem ist seitdem viel Autofac passiert, ich glaube nicht, dass irgendetwas davon mehr relevant ist. –