稍微复杂的对象图

时间:2014-04-08 14:44:11

标签: c# winforms ninject inversion-of-control mvp

我有一位演示者来处理我的表单行为:

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有一个很好的方法吗?我对此很陌生,似乎无法解决这个问题。

2 个答案:

答案 0 :(得分:1)

因此,您希望为每个表单创建一个工作单元。我不会考虑这是否是一个明智的选择。

有几种方法可以实现这一目标:

1 - 手动管理

var unitOfWork = IResolutionRoot.Get<IUnitOfWork>();
IResolutionRoot.Get<Form1Presenter>(new ConstructorArgument("unitOfWork", unitOfWork, true);

在这里你有ninject创建一个工作单元,然后请求一个表单并将unitOfWork作为ConstructorArgument放在请求上。表单及其使用unitOfWork的所有依赖项需要具有构造函数参数IUnitOfWork unitOfWork。名称必须与构造函数参数中指定的名称相同。

所以这是相当多的工作,并没有使用IoC可以提供的所有甜点。所以我不建议使用这种方法。

2命名范围

看看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。因此,您的所有表单都需要定义(相同)范围。此外,表单可能不依赖于另一种形式,因为那样您将有范围重叠。

3通话范围

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>();