我正在编写一个简单的任务运行器应用程序。
我有一堆实现ITask接口的类:
public interface ITask
{
void Run();
}
我正在编写一个简单的控制台应用程序来创建ITasks的实例,然后在每个应用程序上调用Run()。任务实现使用构造函数注入,所以我想使用ninject。
我希望能够在运行时指定要运行哪些任务,以及因此要激活哪些ITask实现。
我在想我可以将具体类型放入我的app.config然后在运行时我可以获得ninject从中构建一个ITask数组。如果做不到这一点,我可以指定我想在命令行上运行的任务。
对我而言,这听起来像是ninject的一个相当直接的案例,但我一直无法找到如何从配置或字符串中绑定ninject。
有人能指出我正确的方向吗?
答案 0 :(得分:6)
ninject有extensions来处理像xml配置这样的事情。
我要小心将配置和Spring XML配置中的编程位混合在一起 - 没有必要转移到XML配置只是为了允许人们在.config文件中配置东西。我建议阅读一个XML配置节加载器,它在一个类中进行序列化,而不是在更高级别表达。
您在绑定注册上使用metadata机制,然后指明如何根据该任务过滤任务集。
例如,重新调整@Ian Davis's answer(去读它并立即投票!):string metaDataKey = "key";
kernel.Bind<IWeapon>().To<Shuriken>().WithMetadata(metaDataKey, true);
kernel.Bind<IWeapon>().To<Sword>().WithMetadata(metaDataKey, false);
kernel.Bind<IWeapon>().To<Knife>();
bool? theOneIWant = null; // or true or false - i.e., the distillation of what your config says
Func<IMetadata> myConfigSaysIWantOneLikeThatPredicate= metadata =>
metadata.Has(metaDataKey) == theOneIWant != null
&& metadata.Get<bool>(metaDataKey) == theOneIWant.Value
var weapons = kernel.Get<IEnumerable<IWeapon>>( myConfigSaysIWantOneLikeThatPredicate );
// the above will generate a single item given the bindings above, but you get the picture - this generates an arbitrary length list
foreach(var weapon in weapons)
weapon.Fire();
如果您要查找的只是能够为它们命名,则会为名为WithMetadata
的{{1}}提供速记替换,并使用名称字符串参数替换Named()
。可以让你实现@dave thieben的简单性,而不需要将你的调用硬连接到Type name。
编辑:示例,见评论:
.Get<T>()
一些垃圾类
using Ninject;
using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;
namespace ninjectmess
{
public class Class1
{
实际测试
public interface ITask
{
}
public class Aasdsdaadsdsa : ITask
{
}
public class Bdsadsadasdsadsadsa : ITask
{
}
public class Cddsadasdsadasdas : ITask
{
}
答案 1 :(得分:3)
我喜欢Ruben的回答,但它可以像在命令行中使用所需任务的类型名称一样简单:
public static void Main( string[] args )
{
var kernel = new StandardKernel();
var tasks = new List<ITask>();
foreach(var taskName in args)
{
tasks.Add( kernel.Get( Type.GetType( taskName ) ) );
}
doSomething(tasks);
}