[英]How can I create an object with ninject using kernel.Get for a binding with a specific attribute?
[英]Using ninject, can I create a binding to a class that has an attribute and satisfies a predicate?
我有一個基類,這些基類可以充當中央系統的插件。 我想允許這些插件在第三方程序集中定義。 中央系統根據一些命令行參數實例化插件。
為此,我創建了一個屬性,可以用這些類來修飾這些屬性,例如:
[ArgName("some-module")]
在它們初始化的時候,我正在使用一段代碼來反映所有已加載的類型,試圖找到具有屬性和適當參數的代碼:
AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(x => x.GetTypes())
.SingleOrDefault(x => /* check for attribute and predicate */);
這很好。
但是我覺得我正在重新發明DI框架可能自己擁有的東西。 因此,由於我已經在項目中將Ninject用於其他依賴項,所以我想知道:還有什么方法可以將這種職責委托給Ninject,而不是編寫自定義的反射代碼嗎?
換句話說,Ninject是否已經有我想念的東西大致執行以下操作:
kernel.Bind<ModuleBase>()
.ToTypesThatHaveThisAttribute<ArgName>()
.With(x => x.Name == userProvidedCommandlineArgument);
當然,我知道我可以為BindingToSyntax<T>
創建上述擴展方法,並使語法在使用的地方更好。 但是,如果Ninject內置此功能,我想完全消除反射代碼。
使用Ninject.Extensions.Conventions
可以實現類似的目的(未經測試)。
string arg = null;
Kernel.Bind(x =>
{
x.FromThisAssembly()
.Select(t =>
{
var attributes = t.GetCustomAttributes(typeof(ArgNameAttribute));
if (attributes.Length == 0) return false;
var attribute = attributes[0];
return attribute.ArgName == arg;
})
.BindSelection((type, interfaces) => new[] {typeof(PluginBase)});
});
但老實說,與手動類型選擇和與Reflection綁定相比,它的代碼量幾乎相同,類似於您編寫的內容。 我的意思是這樣的。
AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(x => x.GetTypes())
.Where(x => {
var attributes = t.GetCustomAttributes(typeof(ArgNameAttribute));
if (attributes.Length == 0) return false;
var attribute = attributes[0];
return attribute.ArgName == arg;
})
.Select(x => Kernel.Bind<PluginBase>().To(x))...
我可能會在沒有Conventions
擴展的情況下這樣做,除非您發現它在其他方面有用。
請注意,這兩個代碼均未測試,僅舉例說明。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.