Ninject - 如何使用Ninject实现命令模式?

时间:2014-12-11 23:15:26

标签: c# command ninject

目前,我正在使用ninject执行命令模式,执行以下绑定:

kernel.Bind<ICommand<InsertParams>>().To<InsertProductCommand>();
kernel.Bind<ICommand<UpdateParams>>().To<UpdateProductCommand>();
kernel.Bind<ICommand<DeleteParams>>().To<DeleteProductCommand>();

我的问题是:这些定义和命令会随着时间的推移而增长。有没有办法将所有这些绑定减少到类似于&#39; Bind(typeof(ICommand&lt;&gt;))&#39;以便根据泛型类型的每个接口都得到适当的解决?

Ex:如果我实现了&#34; ValidateProductCommand&#34;实现&#34; ICommand&#34;无需添加额外的绑定即可自动解析绑定。

感谢。

2 个答案:

答案 0 :(得分:2)

实际上有Ninject.Extensions.Conventions可以帮助你解决这个问题。 然后这很容易做到:

kernel.Bind(x => x.FromThisAssembly()
    .SelectAllClasses()
    .InheritedFrom(typeof(ICommand<>))
    .BindSingleInterface());

完整的测试代码(使用Ninject,Ninject.Extensions.Conventions,xUnit和FluentAssertions nuget包):

using FluentAssertions;
using Ninject;
using Ninject.Extensions.Conventions;
using Xunit;

namespace NinjectTest.ClosedGenericConvention
{
    public interface ICommand<TParam> { }

    public class FloatCommand : ICommand<float> { }

    public class IntCommand : ICommand<int> { }

    public class Test
    {
        [Fact]
        public void Fact()
        {
            var kernel = new StandardKernel();

            kernel.Bind(x => x.FromThisAssembly()
                .SelectAllClasses()
                .InheritedFrom(typeof(ICommand<>))
                .BindSingleInterface());

            kernel.Get<ICommand<float>>().Should().BeOfType<FloatCommand>();
            kernel.Get<ICommand<int>>().Should().BeOfType<IntCommand>();
        }
    }
}

答案 1 :(得分:1)

我无法从您的问题中判断ICommand<T>是您自己的界面还是您正在使用WPF。如果是您的,您可以创建一个非通用的ICommand界面,并让ICommand<T>从中继承。这会让你:

kernel.Bind<ICommand>().To<InsertProductCommand>();
kernel.Bind<ICommand>().To<UpdateProductCommand>();
kernel.Bind<ICommand>().To<DeleteProductCommand>();

然后,您可以使用反射来定位实现ICommand的类并绑定它们。

var types = AppDomain.CurrentDomain.GetAssemblies()
    .SelectMany(s => s.GetTypes())
    .Where(p => typeof(ICommand).IsAssignableFrom(p));

foreach (var type in types) {
    kernel.Bind<ICommand>().To(type);
}

即使你不能让ICommand<T>ICommand下降,你仍然可以通过反思完成它。它有点复杂了。我上面的建议借鉴了下面的(1),但(2)显示了如何直接调整ICommand<T>

  1. Getting all types that implement an interface
  2. .NET - Getting all implementations of a generic interface?
  3. 另外,您可以考虑创建CommandModule : NinjectModule以使与反射相关的绑定远离其他注册。