Asp.net MVP & MVC 之 ASP.NET Model-View-Presenter

The Unity IoC Container can be used in your ASP.NET Web Applications to provide dependency injection, especially when using Model-View-Presenter. There are several ways that one can use Unity to wire-up the presenter class and its dependencies to the ASP.NET view. In this example, I will use a Page Base Class that accesses the UnityContainer on the HttpApplication Class and uses Unity to create an instance of the Presenter Class associated with the view.

First Thoughts - ASP.NET MVC and MVCContrib

Before I jump into this tutorial I would like to mention a similar tutorial on using Unity with the ASP.NET MVC Framework. The reason being that I modeled this tutorial after the ASP.NET MVC and Unity Tutorials:

The technique of adding the UnityContainer via IUnityContainer on the HttpApplication Class was taken from the WindsorControllerFactory in MVCContrib.

Creating and Initializing Unity IoC on HttpApplication Class in Global.asax

We need a way to access the Unity Dependency Injection Container from our websites. Normally I use a ServiceLocator Class, but for this example I thought I would add the Unity Container to the HttpApplication Class as a static variable.

Here is some sample code for adding an initializing the UnityContainer on the HttpApplication Class:

public class Global : HttpApplication, IContainerAccessor
{
    private static IUnityContainer _container;

    public static IUnityContainer Container
    {
        get { return _container; }
    }

    IUnityContainer IContainerAccessor.Container
    {
        get { return Container; }
    }

    protected void Application_Start(object sender, EventArgs e)
    {
        InitializeContainer();
    }

    private static void InitializeContainer()
    {
        if (_container == null)
            _container = new UnityContainer();

        _container
            .RegisterType<IBlogDataSource, BlogDataSource>
(new ContainerControlledLifetimeManager()) .RegisterType<ILogger, NullLogger>()
(new ContainerControlledLifetimeManager())
} }

I have registered a couple of type mappings with Unity. Unity will return BlogDataSource when I request IBlogDataSource and NullLogger when I request ILogger. Both are registered as singletons and I took advantage of the Unity Fluent Interface to register the services. I could have registered these services in a configuration file as well.

In addition, I created a separate interface, called IContainerAccessor that defines access to the IUnityContainer:

public interface IContainerAccessor
{
    IUnityContainer Container { get; }
}

I rather like the interface as it formalizes the process of getting the Unity Container from the HttpApplication Class as we will see in a moment.

Unity IoC and Model-View-Presenter

I have a ASP.NET Page in my web application, called AddBlog that uses Model-View-Presenter to add a blog to my ASP.NET website. The code for my view is as follows:

public partial class AddBlog :
        ViewPage<IAddBlogView,AddBlogPresenter>, IAddBlogView
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!this.IsPostBack)
        {
            Presenter.OnViewInitialized();
        }
        
        Presenter.OnViewLoaded();
    }

    public string BlogTitle
    {
        get { return txtBlogTitle.Text; }
    }

    protected void btnAddBlog_Click(object sender, EventArgs e)
    {
        Presenter.OnAddBlog();
    }
}

The page receives the Click Event of the AddBlog Button and passes the request to the Presenter. In this case I am delegating requests to the presenter. I could have just as easily had the Presenter Class subscribe to various View Events. To each his own.

The ASP.NET Page ( View ) derives from a ViewPage Base Class, which is doing all the work to inject the Presenter into the View using Unity:

abstract public class ViewPage<TView,TPresenter>
    : Page where TPresenter : Presenter<TView> where TView : class
{
    public TPresenter Presenter { get; set; }

    protected void Page_Init(object sender, EventArgs e)
    {
        IContainerAccessor accessor =
            Context.ApplicationInstance as IContainerAccessor;
if (accessor == null || accessor.Container == null)
throw new InvalidOperationException("Cannot Find UnityContainer");
Presenter = container.Resolve<TPresenter>(); Presenter.View = this as TView; } }

We first access the IUnityContainer from the HttpApplication Class and then have the Unity Container create the appropriate Presenter Class and add the view to it.

The Presenter<TView> Class is as follows:

abstract public class Presenter<TView>
{
    public TView View { get; set; }

    virtual public void OnViewInitialized()
    {
    }

    virtual public void OnViewLoaded()
    {
    }
}

and my AddBlogPresenter Class is as follows:

public class AddBlogPresenter : Presenter<IAddBlogView>
{
    private readonly IBlogDataSource _blogDataSource;

    public AddBlogPresenter(IBlogDataSource blogDataSource)
    {
        _blogDataSource = blogDataSource;
    }

    public void OnAddBlog()
    {
        Blog blog = new Blog { Title = View.BlogTitle };
        _blogDataSource.AddBlog(blog);
        // ...
    }
}

All of this means that Unity will create my AddBlogPresenter Class and in turn inject the BlogDataSource Service into it. The BlogDataSource has a dependency on ILogger and Unity will inject NullLogger into BlogDataSource:

public class BlogDataSource : IBlogDataSource
{
    private readonly ILogger _logger;

    public BlogDataSource(ILogger logger)
    {
        _logger = logger;
    }

    public void AddBlog(Blog blog)
    {
        _logger.Log(blog.Title);
    }
}

I didn't appropriately check for null arguments, etc. to keep the code easy-to-read. Make sure you do that in your production applications.

Conclusion

This tutorial on Unity shows one way of using it for IoC and dependency injection needs in your ASP.NET Web Applications. There are other ways to achieve this as well. This tutorial is based on the Unity February 2008 CTP.

I hope it helps.

David Hayden

Tags: DependencyInjection, IoC, ModelViewPresenter, Unity

原文:http://www.pnpguidance.net/Post/UnityIoCDependencyInjectionASPNETModelViewPresenter.aspx

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章