问题
I am creating an ASP.NET Web forms application with MVP pattern. The structure of my view is something like this:
public partial class ShipperView : System.Web.UI.Page, IShipperView
{
ShipperPresenter presenter;
public ShipperOperationsView()
{
IShipperOperations operations = new ShipperOperations();
INavigator navigator = new Navigator();
presenter = new ShipperPresenter(this,operations,navigator); //Instantiating presenter
}
...
}
The basic structure of my presenter is something like this:
public class ShipperPresenter
{
IShipper shipperView;
IShipperOperations operations;
INavigator navigator;
public ShipperPresenter(IShipperView view,IShipperOperations operations,INavigator navigator)
{
shipperView = view;
this.operations = operations;
this.navigator = navigator;
}
...
}
I don't want to instantiate my presenter using the new keyword, I would like to replace it with resolving dependency. During the dependency resolution, I want to pass the instance of the present view to the dependency resolver. I tried searching a lot on this but did not get any satisfactory answer.
Can this issue be resolved using any of the IoC containers like StructureMap, Ninject, Unity or MEF? Any pointer would be of great help.
回答1:
To solve this problem you could use property injection.
First, register ShipperOperations, Navigator and ShipperPresenter in the DI container.
Then, in the Page_Load method of your view, invoke the resolve method of the DI container of your choice.
public class ShipperPresenter
{
IShipper shipperView;
IShipperOperations operations;
INavigator navigator;
public ShipperPresenter(IShipperOperations operations,INavigator navigator)
{
this.operations = operations;
this.navigator = navigator;
}
public IShipper ShipperView
{
get { return shipperView; }
set { shipperView = value; }
}
...
}
And the view would look like this:
public partial class ShipperView : System.Web.UI.Page, IShipperView
{
ShipperPresenter presenter;
protected void Page_Load(object sender, EventArgs e)
{
presenter = YourIOC.Resolve<ShipperPresenter>();
presenter.ShipperView = this;
}
...
}
You could also use a factory to create the presenter at runtime, while passing it the parameters of your choice. In fact, in a DI world, this is THE way to proceed when you want to instantiate objects with dependencies that are only known at runtime. There is a nice mechanism for this in Castle Windsor, it's called typed factories.
Using a factory, no need to modify the presenter class. Instead, create an interface for the factory:
public interface IShipperPresenterFactory
{
ShipperPresenter Create(IShipper shipperView);
}
If using Windsor, the only thing that you have to do is to register this interface as a typed factory. With other DI containers, you will have to implement a class that uses the DI container internally to resolve the presenter.
The Page_Load method of the view would then use the factory like this:
protected void Page_Load(object sender, EventArgs e)
{
var factory = YourIOC.Resolve<IShipperPresenterFactory>();
presenter = factory.Create(this);
}
来源:https://stackoverflow.com/questions/10865695/applying-dependency-injection-on-an-asp-net-web-forms-application-built-using-mv