Ich versuche, MEF 2 in meinem Projekt zu verwenden, verwende ich normalerweise SimpleInjector, aber dieses Mal wollte ich MEF versuchen. Mein Hauptproblem ist, mit offenen Generika tun haben, ist es das, was ichStandardkonstruktor und Open Generics in MEF 2 mit Konventionen
public interface ISetting {}
public class Setting : ISetting {}
public interface ILogger<TLog>
{
TLog Fetch()
}
public class Logger<TLog> : ILogger<TLog>
{
private ISetting settings;
public Logger(ISetting settings)
{
this.settings = settings;
}
public TLog Fetch()
{
return default(TLog);
}
}
Jetzt
für den Behälterteilvar conventions = new ConventionBuilder();
conventions.ForType<Setting>()
.Export<ISetting>()
.Shared();
conventions.ForType(typeof(Logger<>))
.Export(t => t.AsContractType(typeof(ILogger<>)))
.Shared();
var configuration = new ContainerConfiguration()
.WithAssembly(typeof(Program).Assembly,conventions);
using (var container = configuration.CreateContainer)
{
var export = container.GetExport<ILogger<object>>(); //Exception :(
}
ich so weit gekommen, wenn es versucht, den Export abrufen Ich erhalte diese Ausnahme
Es wurde kein importierender Konstruktor für den Typ 'MEFTest.Logger`1 [System.Object]' gefunden.
Wenn ich den Konstruktor aus der Logger-Klasse entfernen, konstruieren die Container die geschlossenen generischen einfach gut. Ich bin 98% sicher, dass das Problem mit den Konstrukteuren verwandt ist, aber ich glaube, ich etwas bin hier fehlt
Edit 1: etwas zu lesen Doing ich tatsächlich entdeckt haben, dass es 2 Versionen von MEF, eine, die eine Nuget ist Paket und ein anderes, das mit .NET40 geliefert wird, ist das Nuget-Paket, das ich verwende. Ich habe einige Refactoring die man zu verwenden, die Schiffe mit .NET40
den Code Alles ist gleich, außer für den Teil, der den Container erstellt und verwenden
var category = new AssemblyCatalog(Assembly.GetExecutingAssembly(), conventions);
using (var container = new CompositionContainer(category))
{
var logic = container.GetExport<ILogger<int>>().Value; //Lazy Initialization O.o
var test = logic.Fetch();
// the rest of the code …
}
Das funktioniert :) ganz gut so auf jeden Fall ich bin etwas in der Version des Pakets Nuget fehlt
Edit 2: Mit der Entfernung der "auto-detection" der generischen Teile im WithAssembly Methode der Code funktioniert, ist hier t Code er refactored
Die Konvention Teil:
var conventions = new ConventionBuilder();
conventions.ForType<Setting>()
.Export<ISetting>();
conventions.ForType<Logger<int>>()
.Export<ILogger<int>>();
Der Teil Behälter:
var types = new Type[] { typeof(Setting), typeof(Logger<int>) };
var configuration = new ContainerConfiguration()
.WithParts(types, conventions);
using (var container = configuration.CreateContainer())
{
var logic = container.GetExport<ILogger<int>>();
var test = logic.Fetch();
// the rest of the code …
}
I die spezifische Art zu ganzen Zahl verändert.Wenn er ausgeführt wird Fetch() es für int korrekt 0 als Standardwert zurückgibt
Der interessante Teil ist, warum die „auto-detection“ der Generika der Konstruktor zwingen
bearbeiten markiert 3: ich denke, der „auto-detection“ Teil hier nicht die Schuld ist, weil ich dies mit zu squar diesem Code
var conventions = new ConventionBuilder();
conventions.ForType<Setting>()
.Export<ISetting>();
conventions.ForType(typeof(Logger<>))
.Export(t => t.AsContractType(typeof(ILogger<>)));
var types = new Type[] { typeof(Setting), typeof(Logger<>) };
var configuration = new ContainerConfiguration()
.WithParts(types, conventions);
using (var container = configuration.CreateContainer())
{
var logic = container.GetExport<ILogger<int>>();
var test = logic.Fetch();
// the rest of the code …
}
versucht habe, ich bin zurück e ein, weil sie die gleiche Ausnahme erzeugt, erzwingt sie die Verwendung des Markierungs Attribut
Bearbeiten 4: Die eigentliche MEF-Projekt auf die Seite unter System.CompositionCoreFx GitHub gegangen ist. Ich ging zu den Unit-Tests und in den RegistrationBuilderCompatibilityTest Linien 40-58
public interface IRepository<T> { }
public class EFRepository<T> : IRepository<T> { }
[Fact]
public void ConventionBuilderExportsOpenGenerics()
{
var rb = new ConventionBuilder();
rb.ForTypesDerivedFrom(typeof(IRepository<>))
.Export(eb => eb.AsContractType(typeof(IRepository<>)));
var c = new ContainerConfiguration()
.WithPart(typeof(EFRepository<>), rb)
.CreateContainer();
var r = c.GetExport<IRepository<string>>();
}
Sie nie ohne den Standard-Konstruktor getestet
Ergebnisse: ich am Ende ein issue auf der CoreFx Github Seite öffnen und übermittelte eine PR mit einer Fehlerbehebung für den Fehler
Ich habe schon versucht 'SelectConstructor (ctr => ctr.FirstOrDefault())' und ist ein Nein. ** BTW ** Wenn ich die Generika von all dem entferne, funktioniert es – TMiNus