簡體   English   中英

我可以使用ninject創建具有屬性並滿足謂詞的類的綁定嗎?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM