我有一位演示者来处理我的表单行为:
public class Form1Presenter
{
IForm1View _view;
IUnitOfWork _unitOfWork;
IService1 _service1;
IService2 _service;
public Form1Presenter(
IForm1View view,
IUnitOfWork unitOfWork,
IService1 service1,
IService2 service2)
{
_view = view;
_unitOfWork = unitOfWork;
_service1 = service1;
_service2 = service2;
}
}
服务注入了与注入上述演示者相同的工作对象单元。像这样:
public class Service1 : IService1
{
IUnitOfWork _unitOfWork;
public Service1(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
}
要手动创建Form1Presenter,我必须做这样的事情:
public class Form1 : Form, IForm1View
{
public Form1()
{
IUnitOfWork unitOfWork = new UnitOfWork();
IService1 service1 = new Service1(unitOfWork);
IService1 service2 = new Service2(unitOfWork);
Form1Presenter presenter = new Form1Presenter(this, unitOfWork, service1, service2);
}
}
使用Ninject有一个很好的方法吗?我对此很陌生,似乎无法解决这个问题。
答案 0 :(得分:1)
因此,您希望为每个表单创建一个工作单元。我不会考虑这是否是一个明智的选择。
有几种方法可以实现这一目标:
var unitOfWork = IResolutionRoot.Get<IUnitOfWork>();
IResolutionRoot.Get<Form1Presenter>(new ConstructorArgument("unitOfWork", unitOfWork, true);
在这里你有ninject创建一个工作单元,然后请求一个表单并将unitOfWork作为ConstructorArgument放在请求上。表单及其使用unitOfWork的所有依赖项需要具有构造函数参数IUnitOfWork unitOfWork
。名称必须与构造函数参数中指定的名称相同。
所以这是相当多的工作,并没有使用IoC可以提供的所有甜点。所以我不建议使用这种方法。
看看Ninject Named Scope Extension。 按如下方式创建绑定:
const string UnitOfWorkScopeName = "UnitOfWorkScopeName";
IBindingRoot.Bind<IUnitOfWork>().To<UnitOfWork>()
.InNamedScope(UnitOfWorkScopeName);
IBindingRoot.Bind<Form1Presenter>().ToSelf()
.DefinesNamedScope(UnitOfWorkScopeName);
IBindingRoot.Bind<Form2Presenter>().ToSelf()
.DefinesNamedScope(UnitOfWorkScopeName);
IBindingRoot.Bind<Form3Presenter>().ToSelf()
.DefinesNamedScope(UnitOfWorkScopeName);
这将导致所有与DefinesNamedScope
绑定的对象及其所有依赖项都获得IUnitOfWork
的相同实例。
但是,当您不在正确的范围内时,您永远不能实现IUnitOfWork
。因此,您的所有表单都需要定义(相同)范围。此外,表单可能不依赖于另一种形式,因为那样您将有范围重叠。
InCallScope()
表示由一个IResolutionRoot.Get()创建的所有对象都将接收相同的对象。
IBindingRoot.Bind<IUnitOfWork>().To<UnitOfWork>()
.InCallScope();
不需要调整所有其他组件的绑定。
如果您通过一次调用IResolutionRoot.Get()
来实现多个表单,这不起作用
当然,您可以通过更多方式管理工作单元的生命周期。
我们已将会话管理与IUnitOfWork分离,并使用ThreadLocal
来确定是否需要启动新的会话/事务或使用现有的会话/事务。
答案 1 :(得分:0)
安装Ninject.Extensions.Conventions然后你可以将所有类绑定到他们的默认界面(前面带有“I”的类名),如下所示
IKernel kernel = new StandardKernel();
kernel.Bind(x =>
x.FromThisAssembly() // Scans currently assembly
.IncludingNonePublicTypes() // Including Non-public types
.SelectAllClasses() // Retrieve all non-abstract classes
.BindDefaultInterface()); // Binds the default interface to them, e.g. class name without preceding "I"
var Form1Presenter = kernel.Get<Form1Presenter>();