[英]Default constructor and open generics in MEF 2 using conventions
我正在嘗試在項目中使用MEF 2,通常使用SimpleInjector,但是這次我想嘗試MEF。 我的主要問題是處理開放式泛型,這就是我到目前為止所得到的
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);
}
}
現在我要做容器部分
var 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 :(
}
當嘗試檢索導出時,出現此異常
在類型'MEFTest.Logger`1 [System.Object]'上未找到導入構造函數。
如果我從Logger類中刪除構造函數,則容器構造封閉的泛型就可以了。 我有98%的把握是問題與構造函數有關,但我覺得這里遺漏了一些東西
編輯1:做一些閱讀,我實際上發現有2個版本的MEF,一個是Nuget軟件包,另一個是.NET40附帶的版本,我使用的是Nuget軟件包。 我進行了一些重構以使用.NET40附帶的組件
除了創建和使用容器的部分外,所有代碼都是相同的
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 …
}
這有效:)很好,所以我肯定在Nuget軟件包的版本中缺少某些內容
編輯2:刪除了WithAssembly方法中通用零件的“自動檢測”功能后,代碼起作用了,這里是重構的代碼
約定部分:
var conventions = new ConventionBuilder();
conventions.ForType<Setting>()
.Export<ISetting>();
conventions.ForType<Logger<int>>()
.Export<ILogger<int>>();
容器部分:
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 …
}
我將特定類型更改為integer 。當它執行Fetch()時,它會正確返回0作為int的默認值
有趣的部分是為什么泛型的“自動檢測”會強制標記構造函數
編輯3:我認為“自動檢測”部分不是這里的錯誤,因為我已經嘗試過
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 …
}
有了該代碼,我回到正題,因為它會產生相同的異常,它會強制使用marking屬性
編輯4:實際的MEF項目已轉到System.Composition下的CoreFx GitHub頁面。 我去了單元測試,並在RegistrationBuilderCompatibilityTest行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>>();
}
沒有默認的構造函數,他們從未測試過它
嘗試使用[ImportingConstructor]屬性標記構造函數。
using System.Composition;
...
[ImportingConstructor]
public Logger(ISetting settings)
{
this.settings = settings;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.