过去,我使用swiftsuspenders作为动作脚本3 IoC控制器。基本上,switfsuspender的第一个版本与Ninject内核类似,称为注入器。
如果我想创建一个应用程序注入器(假设在整个应用程序中使用最相关的映射),我必须在应用程序类中注入注入器。
我想知道现在使用kernel.get<>的做法是什么?在应用程序的几个类之间。我应该自己注入内核吗?
我个人更喜欢使用kernel.inject但是如果我能做kernel.inject我真的可能会手动注入依赖项,这可能更好(亲吻)。
测试用例很好,但它们远非实际的实际问题,所以我希望你能帮助我澄清这一点。谢谢。
编辑:我注意到有些人谈论“根容器”,似乎这是我正在寻找的概念。我应该如何设置根容器并让其他应用程序类知道它?
Edit2示例代码(请原谅错误,仅作为示例):
class SomeClass
{
public SomeClass()
{
Command cmd = new Command();
cmd.execute();
}
}
class SomeOtherClass:ISomeOtherClass
{
public void allright()
{
//right
}
}
class Command
{
ISomeOtherClass dependency;
void execute()
{
dependency.allright();
}
}
Program.Main()
{
IKernel kernel = new StandardKernel();
kernel.Bind<SomeClass>().ToSelf().InSingletonScope();
kernel.Bind<ISomeOtherClass>().To<SomeOtherClass>();
SomeClass sc = kernel.Get<SomeClass>();
}
我还没有对此进行测试,因为我仍然在解决一些初始化问题,但我的问题是,命令类如何知道SomeOtherClass?我目前的假设是在SomeClass中注入内核并使用Inject方法。
答案 0 :(得分:11)
看看你的例子,很明显SomeClass
并没有考虑到控制反转;提示是它依赖于Command
,但在SomeClass
本身内部保持对该依赖的控制。 (Command cmd = new Command();
)
要反转该依赖项的控件,您需要有一种方法将该依赖项注入SomeClass。作为Remo Gloor has indicated,Ninject的标准方法是通过构造函数。
为此,您可以将SomeClass更改为以下内容:
class SomeClass
{
private ICommand _command;
public SomeClass(ICommand injectedCommand)
{
_command = injectedCommand;
_command.execute();
}
}
同样,你需要你的Command来宣传它的依赖:
class Command
{
private ISomeOtherClass _dependency;
public Command(ISomeOtherClass injectedSomeOtherClass)
{
_dependency = injectedSomeOtherClass;
{
void execute()
{
_dependency.allright();
}
}
然后你会在内核中注册你的Command绑定,也许就像:
Program.Main()
{
IKernel kernel = new StandardKernel();
kernel.Bind<SomeClass>().ToSelf().InSingletonScope();
kernel.Bind<ICommand>().To<Command>();
kernel.Bind<ISomeOtherClass>().To<SomeOtherClass>();
SomeClass sc = kernel.Get<SomeClass>();
}
然后内核可以遍历依赖链并将它们全部注入。
答案 1 :(得分:5)
尽可能使用构造函数注入和Factories,只要有充分的理由不与依赖它们的对象一起创建实例。
仅当您不更改对象的创建时,才应使用 kernel.Inject
。例如。一个WebForm
kernel.Get
应该只在合成根目录中使用一次(例如Program.Main或MVC3.DependencyResolver)来创建你的应用程序。