6

我正在尝试使用 winforms 应用程序来降低 IoC 的概念。假设我有一个演示者,其构造函数将其视图和服务作为构造函数参数。所以在表单代码中我有一些相当于这个的东西:

mnPresenter = new Presenter(this, new AppService());

其中,AppService 是 IAppService 的一个实现。它在我的[autofac]IoC 容器中注册。从这个演示者结构中获得“新”的推荐方法是什么?像我上面所说的那样,使用 IoC 框架来丢失这些“新”调用的重点不是吗?

我可以做类似的事情

mPresenter = new Presenter(this, MyContainer.Resolve<IAppService>())

但这似乎违背了 IoC 的目的。我可能在这里遗漏了一些基本的东西。

如果我遗漏了一些明显的东西,请提前道歉。

4

2 回答 2

9

您的问题是 View 和 Presenter 之间存在依赖循环,因为它们相互依赖。打破这种依赖循环的一般规则是回退到属性注入,这也适用于您的情况。

使用 MVP,最好是让 View 通过将其注入到 Presenter 的属性中来将自己分配给创建的 Presenter:

mPresenter = container.Resolve<Presenter>();
mPresenter.View = this;

如果可以,请从应用程序中隐藏容器。由于您使用的是 MVP,因此您唯一需要直接解决的就是演示者。因此,与其让 Forms 与 Container 通信,不如让它们与 static 通信PresenterFactory。这家工厂将使用盖子下的容器:

mPresenter = PresenterFactory.Create<MyPresenter>();
mPresenter.View = this;

PresenterFactory可能看起来像这样:

public static class PresenterFactory
{
    private static IContainer container;

    public static TPresenter Create<TPresenter>()
        where TPresenter : IPresenter
    {
        return (TPresenter)
            container.Resolve(typeof(TPresenter));
    }

    public static void SetContainer(IContainer container)
    {
        PresenterFactory.container = container;
    }
}

您的 Composition Root 可能如下所示:

static void Main()
{
    Bootstrap();
}

private static void Bootstrap()
{
    var builder = new ContainerBuilder();
    // TODO: register presenters

    var container = builder.Build();

    PresenterFactory.SetContainer(container);
}

更新

也许做这样的事情会更好:

interface IPresenter<TView>
{
    TView View { get; set; }
}

public static class PresenterFactory
{
    private static IContainer container;

    public static IPresenter<TView> CreateForView<TView>(TView view)
    {
        var presenter = container.Resolve<IPresenter<TView>>();
        presenter.View = view;
        return presenter;
    }
}

// View
mPresenter = PresenterFactory.CreateForView(this);

这从视图中隐藏了演示者的实际实现,并将视图的注册集中到演示者。

于 2012-07-31T10:37:49.750 回答
1

您需要演示者中的属性

public IAppService service;

它将由容器注入,您无需将其作为参数传递。你写的是服务定位器,实际上是 IoC 的反模式。

如果您的视图也是强类型并在容器中注册,您可以使用 Autofac 的 .SingleInstance 生命周期和属性

public IMyView view;

在您的展示中,容器会将视图实例注入您的展示器。

您基本上是在另一个问题中查看代码: Register a Presenter with a View

于 2012-11-08T13:36:20.333 回答