.net 如何使用IoC容器组织MVP?

.net 如何使用IoC容器组织MVP?,.net,winforms,inversion-of-control,autofac,.net,Winforms,Inversion Of Control,Autofac,我正试图用winforms应用程序来降低国际奥委会的概念。假设我有一个演示者,其构造函数将其视图和服务作为构造函数参数。因此,在表单代码中,我有一个相当于以下内容: mnPresenter = new Presenter(this, new AppService()); 其中,假设AppService是IAppService的一个实现。它已在我的[autofac]IoC容器中注册。从这个演示者结构中获得“新”的推荐方法是什么?使用国际奥委会框架来丢失这些“新”的呼吁,难道不是我上面所说的全部意

我正试图用winforms应用程序来降低国际奥委会的概念。假设我有一个演示者,其构造函数将其视图和服务作为构造函数参数。因此,在表单代码中,我有一个相当于以下内容:

mnPresenter = new Presenter(this, new AppService());
其中,假设AppService是IAppService的一个实现。它已在我的
[autofac]
IoC容器中注册。从这个演示者结构中获得“新”的推荐方法是什么?使用国际奥委会框架来丢失这些“新”的呼吁,难道不是我上面所说的全部意义吗

我可以做类似的事情

mPresenter = new Presenter(this, MyContainer.Resolve<IAppService>())
mPresenter=新的演示者(这是MyContainer.Resolve())
但这似乎违背了国际奥委会的宗旨。我可能遗漏了一些基本的东西


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

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

使用MVP,最好的方法是通过将视图注入到演示者的属性中,将其自身分配给已创建的演示者:

mPresenter=container.Resolve();
mPresenter.View=this;
如果可以,请对应用程序隐藏容器。因为您使用的是MVP,所以您唯一需要直接解决的问题就是演示者。因此,与其让表单与容器通信,不如让表单与静态的
PresenterFactory
通信。该工厂将使用盖子下的容器:

mPresenter = PresenterFactory.Create<MyPresenter>();
mPresenter.View = this;
您的合成根可能如下所示:

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;
    }
}
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);
更新

也许这样做更好:

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;
    }
}
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);
接口IPresenter
{
TView视图{get;set;}
}
公共静态类PresenterFactory
{
专用静态集装箱;
公共静态IPresenter CreateForView(TView视图)
{
var presenter=container.Resolve();
presenter.View=视图;
返回演讲者;
}
}
//看法
mPresenter=PresenterFactory.CreateForView(此);

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

您需要演示者中的属性

public IAppService service;
它将由容器注入,您不需要将其作为参数传递。您编写的是一个服务定位器,实际上是一个针对IoC的反模式

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

public IMyView view;
在演示文稿中,容器随后将视图实例注入演示文稿中

您基本上可以在另一个问题中查看代码:

很抱歉,我花了这么长时间才回复。谢谢你回复我,史蒂文,谢谢你的建议。把你的建议付诸实践,喜欢它的运作方式。再次感谢。非常感谢这条建议,它帮我摆脱了一点困境;)如果您碰巧正在使用Autofac进行此操作,并且在注册开放泛型时遇到问题,那么您并不是唯一一个这样做的人:这里有一个关于它的讨论。感谢您的回复。我可能知道你在说什么,但是如果你有时间,一个代码示例,即使是一个简短的,都会很有帮助。再次感谢。罗布,我的回复中有一个链接,最后一行。好的,谢谢。我误解了你的答案。我以为你在用这个链接来说明什么是不应该做的。我很感激你能再次回复我。