使用ninject,我可以创建一个绑定到一个具有属性并满足谓词的类
本文关键字:一个 属性 满足 谓词 我可以 ninject 使用 绑定 创建 | 更新日期: 2023-09-27 18:06:01
我有一个基类,用于可以作为中央系统插件的类。我想允许这些插件在第三方程序集中定义。中央系统根据一些命令行参数实例化插件。
为了实现这一点,我创建了一个属性,这些类可以用它来装饰,类似于:[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)});
});
但说实话,与手动类型选择和反射绑定相比,这几乎是相同数量的代码,类似于您编写的代码。我的意思是这样的。
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
扩展,除非你发现它在其他方面很有用。
请注意,这两个代码都没有经过测试,我只添加了它们,例如