如何通过Ninject提供额外的参数?

时间:2019-04-03 05:09:54

标签: c# dependency-injection inversion-of-control ninject

我需要自动解决Windows窗体的依赖性。唯一的问题是我的表单构造函数也期望一个整数值。请在代码部分中查看实现。

   //Ninject bindings
   public class Bindings : NinjectModule
    {
        public override void Load()
        {
            Bind<ILogger>().To<LogToDB>();
            Bind<ICopy>().To<CopyToFolder>();            
        }
    }

  //WinForm - Form1
   public partial class Form1 : Form
    {
        public readonly ILogger _processRepository;
        public readonly Icopy _copy;
        public readonly int ValueToEdit;
        public Form1(int valueToEdit, ILogger logger, ICopy copy)
        {
            this._processRepository = logger;
            this._copy = copy;
            this.ValueToEdit = valueToEdit;
            InitializeComponent();
        }
    }
    //main
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        IKernel kernel = new StandardKernel(new Bindings());            
        Application.Run(kernel.Get<Form1>());            
    }

我得到一个错误: Ninject.ActivationException:'激活int时出错 没有匹配的绑定可用,并且类型不可自绑定。

如何自动解决表单依赖关系并能够传递整数值?实际上,我使用相同的表单进行添加和编辑,因此在编辑时,应设置此编辑值。

2 个答案:

答案 0 :(得分:3)

我想解决这个问题的最干净的方法是创建工厂:

interface IForm1Factory
{
    Form1 Create(int valueToEdit);
}

class Form1Factory
{
    public readonly ILogger _processRepository;
    public readonly Icopy _copy;

    public Form1Factory(ILogger logger, ICopy copy)
    {
        this._processRepository = logger;
        this._copy = copy;
    }

    public Form1 Create(int valueToEdit)
    {
        return new Form1(valueToEdit, _processRepository, _copy);
    }
}

还有一个扩展名(Ninject.Extensions.Factory),使您可以基于接口自动生成工厂,例如Form1Factory。如果使用该扩展名,则使用Bind<IForm1Factory>().ToFactory()声明。

答案 1 :(得分:0)

using Ninject;
using Ninject.Modules;
using Ninject.Parameters;  
//Add new class  
public class CompositionRoot
{
    public static IKernel _ninjectKernel;
    public static void Wire(INinjectModule module)
    {
        _ninjectKernel = new StandardKernel(module);
    }
    public static T Resolve<T>()
    {
        return _ninjectKernel.Get<T>();
    }
    public static T ResolveWithArgument<T>(ConstructorArgument argument)
    {
        return _ninjectKernel.Get<T>(argument);
    }
}

//Ninject bindings
public class Bindings : NinjectModule
{
    public override void Load()
    {
        Bind<ILogger>().To<LogToDB>();
        Bind<ICopy>().To<CopyToFolder>();            
    }
}

//WinForm - Form1
public partial class Form1 : Form
{
    public readonly ILogger _processRepository;
    public readonly Icopy _copy;
    public readonly int ValueToEdit;
    public Form1(ILogger logger, ICopy copy, int valueToEdit)
    {
        this._processRepository = logger;
        this._copy = copy;
        this.ValueToEdit = valueToEdit;
        InitializeComponent();
    }
}

//main
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
   //Apply the binding rule first
   CompositionRoot.Wire(new Bindings());   
   //Then resolve your form dependencies this way using Ninject passing along the 
   constructor arguments. 
   CompositionRoot.ResolveWithArgument<Form1>(new ConstructorArgument("valueToEdit", 
   1)).ShowDialog();      
}