使用Ninject在构造函数中使用附加参数创build一个实例

我决定开始使用Ninject,并面临一个问题。 说我有以下情况。 我有一个IService接口和2个类来实现这个接口。 而且我也有一个类,它有一个构造函数获得IService和一个int 。 我怎样才能创build这个类的实例与Ninject(我不想强硬这个int,我想每次我得到一个实例时通过它)?

以下是一些说明情况的代码:

 interface IService { void Func(); } class StandardService : IService { public void Func() { Console.WriteLine("Standard"); } } class AlternativeService : IService { public void Func() { Console.WriteLine("Alternative"); } } class MyClass { public MyClass(IService service, int i) { this.service = service; } public void Func() { service.Func(); } IService service = null; } class Program { static void Main(string[] args) { IKernel kernel = new StandardKernel(new InlineModule( x => x.Bind<IService>().To<AlternativeService>(), x => x.Bind<MyClass>().ToSelf())); IService service = kernel.Get<IService>(); MyClass m = kernel.Get<MyClass>(); m.Func(); } } 

With.ConstructorArgument存在于1.0中。 在2.0中,语法稍微改变了: – With.Parameters.ConstructorArgument与ninject 2.0

有关如何使用上下文,提供程序和参数更正确地传递此类信息的更多详细信息和示例,请参阅将注入值注入到注入的依赖项中。

编辑:由于史蒂文已经select假装我的评论是无关紧要的,我最好弄清楚我说的一些例子(为2.0):

 MyClass m = kernel.Get<MyClass>( new ConstructorArgument( "i", 2) ); 

这对我来说是非常清楚的,并确切地说明发生了什么。

如果您处于可以更全面地确定参数的位置,那么您可以注册一个提供者,并像这样执行:

 class MyClassProvider : SimpleProvider<MyClass> { protected override MyClass CreateInstance( IContext context ) { return new MyClass( context.Kernel.Get<IService>(), CalculateINow() ); } } 

并注册它像这样:

 x => x.Bind<MyClass>().ToProvider( new MyClassProvider() ) 

注意, CalculateINow()位是您在第一个答案中放置逻辑的位置。

或者让它更复杂,如下所示:

 class MyClassProviderCustom : SimpleProvider<MyClass> { readonly Func<int> _calculateINow; public MyClassProviderCustom( Func<int> calculateINow ) { _calculateINow = calculateINow; } protected override MyClass CreateInstance( IContext context ) { return new MyClass( context.Kernel.Get<IService>(), _calculateINow() ); } } 

你会这样注册:

 x => x.Bind<MyClass>().ToProvider( new MyClassProviderCustom( ( ) => new Random( ).Next( 9 ) ) ) 

更新: Ninject.Extensions.Factory扩展中体现了更新的机制,其展示了大大改进的模式,比上面更less的样板Ninject.Extensions.Factory ,请参阅: https : //github.com/ninject/ninject.extensions.factory/wiki

如前所述, 如果每次需要传递不同的参数,并且在依赖关系图中有多个级别,则可能需要执行类似的操作 。

最后一点需要注意的是,因为你没有指定一个Using<Behavior> ,所以默认情况下默认为内核选项中指定/默认的默认值(示例中的TransientBehavior ),这可能会导致工厂计算i on飞行模拟[例如,如果它的对象被caching]

现在,澄清正在被欺骗和掩盖的评论中的其他一些观点。 一些重要的事情要考虑使用DI,无论是Ninject还是其他任何事情:

  1. 尽可能通过构造函数注入完成,所以你不需要使用容器特定的属性和技巧。 有一个很好的博客文章,称为你的IoC容器显示 。

  2. 尽量减less到容器的代码和要求的东西 – 否则你的代码被耦合到特定的容器(CSL可以最小化)b)整个项目的布局方式。 有很好的博客文章表明,CSL没有做你认为的事情。 这个一般的主题被称为服务位置vsdependency injection 。 更新:请参阅http://blog.ploeh.dk/2011/07/28/CompositionRoot.aspx获取详细和完整的基本原理。;

  3. 最大限度地减less静态和单身的使用

  4. 不要以为只有一个[全局]容器,只要需要它就可以了,就像一个好的全局variables一样。 正确使用多个模块和Bind.ToProvider()给你一个结构来pipe理这个。 这样,每个独立的子系统都可以独立工作,而且不会将低级别组件绑定到顶级组件等。

如果有人想填写我指的博客的链接,我会很感激(虽然他们都已经从其他post链接,所以这只是UI've引入的重复避免混淆误导的答案。)

现在,如果只有乔尔可以进来,并真正让我直说什么好的语法和/或正确的方式来做到这一点!

更新:虽然这个答案显然是有用的upvotes它的数量,我想提出以下build议:

  • 以上感觉有点过时了,说实话反映了很多不完整的思考,因为阅读.net中的dependency injection几乎感到尴尬 – 现在运行和购买 – 这不仅是关于DI,上半年是一个完整的处理所有的架构问题都是围绕在dependency injection标签上的一个人,
  • 现在就阅读马克·西曼(Mark Seemann)的评分最高的post – 你将会从每一个人那里学到有价值的技巧