运行时绑定:一个简单的任务运行器与ninject?

Twi*_*ted 6 ninject

我正在编写一个简单的任务运行器应用程序.

我有一堆实现ITask接口的类:

public interface ITask
{
   void Run();
}
Run Code Online (Sandbox Code Playgroud)

我正在编写一个简单的控制台应用程序来创建ITasks实例,然后在每个应用程序上调用Run().任务实现使用构造函数注入,所以我想使用ninject.

我希望能够在运行时指定要运行哪些任务以及因此要激活哪些ITask实现.

我想我可以将具体类型放入我的app.config然后在运行时我可以获得ninject从中构建一个ITask数组.如果做不到这一点,我可以指定我想在命令行上运行的任务.

对我来说,这听起来像ninject的一个相当直接的案例,但我一直无法找到如何从配置或字符串绑定ninject.

任何人都能指出我正确的方向吗?

Rub*_*ink 6

有ninject的扩展可以处理xml配置之类的东西.

我要小心将Spring和Spring配置中的编程位混合起来 - 没有必要转移到XML配置只是为了让人们在.config文件中配置东西.我建议阅读一个XML配置节加载器,它在一个表示序列化的类中表示更高级别.

您将在Binding注册上使用元数据机制,然后指示如何基于此过滤任务集.

例如,重新利用@Ian Davis的答案(去读它并立即投票!):

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();
Run Code Online (Sandbox Code Playgroud)

如果您正在寻找的只是能够命名它们,那么可以使用名称字符串参数替换WithMetadata被调用Named()和重载.Get<T>(),这样可以实现@dave thieben的简单性,而无需将您的调用硬连接到类型名称.

编辑:示例,请参阅注释:

using Ninject;
using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;

namespace ninjectmess
{
    public class Class1
    {
Run Code Online (Sandbox Code Playgroud)

一些垃圾类

        public interface ITask
        {
        }

        public class Aasdsdaadsdsa : ITask
        {
        }
        public class Bdsadsadasdsadsadsa : ITask
        {
        }
        public class Cddsadasdsadasdas : ITask
        {
        }
Run Code Online (Sandbox Code Playgroud)

实际测试

        [Fact]
        public void TestMethod()
        {
            var k = new StandardKernel();
            k.Bind<ITask>().To<Aasdsdaadsdsa>().Named( "A" );
            k.Bind<ITask>().To<Bdsadsadasdsadsadsa>().Named( "B" );
            k.Bind<ITask>().To<Cddsadasdsadasdas>().Named( "C" );

            var wanted = new string[] { "A", "C" };

            var tasks = k
                .GetAll<ITask>( metadata => wanted.Contains( metadata.Name ))
                .ToList();
            Assert.Equal( 2, tasks.Count );
            tasks.ForEach( Console.WriteLine );
        }
    }
}
Run Code Online (Sandbox Code Playgroud)