.net 如何使用IoC容器组织MVP?
我正试图用winforms应用程序来降低国际奥委会的概念。假设我有一个演示者,其构造函数将其视图和服务作为构造函数参数。因此,在表单代码中,我有一个相当于以下内容:.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容器中注册。从这个演示者结构中获得“新”的推荐方法是什么?使用国际奥委会框架来丢失这些“新”的呼吁,难道不是我上面所说的全部意
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进行此操作,并且在注册开放泛型时遇到问题,那么您并不是唯一一个这样做的人:这里有一个关于它的讨论。感谢您的回复。我可能知道你在说什么,但是如果你有时间,一个代码示例,即使是一个简短的,都会很有帮助。再次感谢。罗布,我的回复中有一个链接,最后一行。好的,谢谢。我误解了你的答案。我以为你在用这个链接来说明什么是不应该做的。我很感激你能再次回复我。