Stu*_*ens 63 c# ninject ioc-container
我决定开始使用Ninject并面临一个问题.说我有以下场景.我有一个IService接口和2个实现此接口的类.而且我还有一个类,它有一个构造函数获取IService和一个int.如何使用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();
}
}
Run Code Online (Sandbox Code Playgroud)
Rub*_*ink 93
该With.ConstructorArgument为此,在1.0中存在.在2.0中,语法略有改变: -
With.Parameters.ConstructorArgument with ninject 2.0
有关更多详细信息,请参阅将值注入到注入的依赖项中,以及如何使用上下文,提供程序和参数更正确地传递此类内容的示例.
编辑:由于史蒂文选择假装我的评论无关紧要,我最好用一些例子(对于2.0)说清楚我在说什么:
MyClass m = kernel.Get<MyClass>( new ConstructorArgument( "i", 2) );
Run Code Online (Sandbox Code Playgroud)
我的眼睛非常清楚,并准确说明发生了什么.
如果您处于可以以更全局的方式确定参数的位置,则可以注册提供程序并按以下方式执行:
class MyClassProvider : SimpleProvider<MyClass>
{
protected override MyClass CreateInstance( IContext context )
{
return new MyClass( context.Kernel.Get<IService>(), CalculateINow() );
}
}
Run Code Online (Sandbox Code Playgroud)
并注册如下:
x => x.Bind<MyClass>().ToProvider( new MyClassProvider() )
Run Code Online (Sandbox Code Playgroud)
注意,这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() );
}
}
Run Code Online (Sandbox Code Playgroud)
你注册的是这样的:
x => x.Bind<MyClass>().ToProvider( new MyClassProviderCustom( ( ) => new Random( ).Next( 9 ) ) )
Run Code Online (Sandbox Code Playgroud)
更新:Ninject.Extensions.Factory扩展中体现了更新的机制,其中显示了大大改进的模式,并且具有比上述更少的样板,请参阅:https:
//github.com/ninject/ninject.extensions.factory/wiki
如前所述,如果每次需要传递一个不同的参数,并且在依赖关系图中有多个级别,则可能需要执行类似这样的操作.
最后一个考虑因素是因为你没有指定a Using<Behavior>,它将默认为默认的内核选项中的指定/默认值(TransientBehavior在样本中),这可能会导致工厂i在飞行中计算的事实[例如,如果对象被缓存]
现在,澄清正在评论和掩饰的评论中的其他一些观点.关于使用DI的一些重要事项,无论是Ninject还是其他任何东西:
尽可能通过构造函数注入完成,因此您不需要使用容器特定的属性和技巧.有一篇很好的博客文章称为你的IoC容器正在展示.
最小化代码进入容器并询问内容 - 否则您的代码将耦合到a)特定容器(CSL可以最小化)b)整个项目的布局方式.有很好的博客文章显示CSL没有做你认为它做的事情.此常规主题称为服务位置与依赖注入.更新:有关详细和完整的基本原理,请参阅http://blog.ploeh.dk/2011/07/28/CompositionRoot.aspx.
尽量减少使用静力学和单身人士
不要假设只有一个[全局]容器,只要你需要它就像一个好的全局变量就可以.正确使用多个模块并Bind.ToProvider()为您提供管理此结构的结构.这样,每个独立的子系统都可以单独工作,并且您不会将低级组件绑定到顶级组件等.
如果有人想填写我所指的博客的链接,我会很感激(虽然所有这些都已经在其他帖子中链接了所以这些只是重复的UI已经引入了目标避免混淆误导性答案.)
现在,如果只有Joel可以进来并真正让我直截了当地说出了很好的语法和/或正确的方法!
更新:虽然这个答案从获得的赞成数量中显而易见,但我想提出以下建议:
| 归档时间: |
|
| 查看次数: |
51628 次 |
| 最近记录: |