views:

261

answers:

3

I have an ASP.NET page that implements my view and creates the presenter in the page constuctor. Phil Haack's post providing was used as the starting point, and I'll just the examples from the post to illustrate the question.

public partial class _Default : System.Web.UI.Page, IPostEditView {

    PostEditController controller;
    public _Default()
    {
         this.controller = new PostEditController(this, new BlogDataService());
    }
}

What is the best approach to inject the instance of the BlogDataService? The examples I have found use properties in the Page class for the dependency marked with an attribute which the injection framework resolves.

However, I prefer using the constructor approach for testing purposes.

Does anyone have input or perhaps links to good implementations of the above. I would prefer Ninject, but StructureMap or Windsor would be fine as long as its fluent.

Thanks for any feedback.

+2  A: 

If you use the Microsoft ServiceLocator, you can apply the service locator design pattern and ask the container for the service.

In your case it would look something like this:

public partial class _Default : System.Web.UI.Page, IPostEditView {

    PostEditController controller;
    public _Default()
    {
         var service = ServiceLocator.Current.GetInstance<IBlogDataService>();
         this.controller = new PostEditController(this, service);
    }
}

ServiceLocator has implementations for Castle Windsor and StructureMap. Not sure about Ninject, but it's trivial to create a ServiceLocator adapter for a new IoC.

Neil Barnwell
I like it, thanks.
blu
Using this approach, the view now knows about the IBlogDataService which should only have been known to the presenter. Is there a way to construct the presenter using a DI container passing in the current view object and the configured IBlogDataService instance?
Scott
+1  A: 

I haven't seen a general purpose method for doing constructor injection on webforms. I assume it may be possible via a PageFactory implementation, but since most on the edge right now are moving to MVC rather than webforms, that may not happen.

However, autofac (a DI container I like a lot) has an integration module for ASP.NET WebForms that does property injection without attributes - your code would look like this :

public partial class _Default : System.Web.UI.Page, IPostEditView {

    public IBlogDataService DataService{get;set;}
    public _Default()
    {
    }
}

I know this doesn't specifically solve your desire to use constructor injection, but this is the closest I know of.

Philip Rieck
Will the container guarantee the property is set prior to the constructor code being called? Feels a little chicken and the egg to me.
blu
No, the property will be set after the constructor is called. One of the pains of webforms, I'm afraid.
Philip Rieck
I ended up using autofac instead of ServiceLocator, but in the style Neil has above. Thanks for this.
blu
A: 

In our homegrown MVP-framework we had a typed base-class that all Pages inherited from. The type needed to be of type Presenter (our base presenter class)

In the base-class we then initialized the controller using the IoC-container.

Sample code:

public class EditPage : BasePage<EditController> {
}

public class EditController : Presenter {
 public EditController(IService service) { }
}

public class BasePage<T> : Page where T: Presenter
{
 T Presenter { get; set; }
 public BasePage() { 
  Presenter = ObjectFactory.GetInstance<T>(); //StructureMap
 }
}

Hope this helps!

Kenny Eliasson