Click here to Skip to main content
15,861,125 members
Articles / Programming Languages / C#
Article

Building an MVP Framework for .NET. Part 4: Strongly Typed Associations

Rate me:
Please Sign up or sign in to vote.
4.86/5 (4 votes)
25 Apr 2008Ms-PL2 min read 27.4K   339   31  
In this article we continue developing a Model-View-Presenter framework for .NET platform. The new features we are implementing here are strongly typed asscoiations between controllers, views and tasks for higher convenience and type safety.

Introduction

In the previous parts (1, 2, 3) we have constructed a quite usable and functional framework. However, it still has some drawbacks. One of them is the necessity of typecasting when accessing controllers, views and tasks. The example below demonstrates such typecasting:

C#
public class ProductsView : WebFormView, IProductsView
    ...
    private void ShowProductDetailsButton_Click(object sender, EventArgs e)
    {
        (Controller as ProductsController).ShowProductDetails(); // typecasting required

    }

As a system grows such typecasts may bloat code, excessively decreasing its readability and leading to errors. To eliminate this drawback we need a means of explicitly specifying the type of the associated controller (or view/task). In other words we need to make associations between tasks, controllers and views strongly typed.

Solution Outline

The most obvious solution is to isolate the typecasing operation in a new property of the required type:

C#
public class ProductsView : WebFormView, IProductsView
    ...
    private new ProductsController Controller
    {
        get { return base.Controller as ProductsController; }
        set { base.Controller = value; }
    }

    private void ShowProductDetailsButton_Click(object sender, EventArgs e)
    {
        Controller.ShowProductDetails(); // typecasting NOT required

    }

Although acceptable, this solution requires several additional lines of code. A more elegant solution can be constructed with a handy feature of .NET framework called Generics. The generics mechanism allows varying a class members' types by specifying those types in the class declaration. For example, it is possible to adjust a return type for certain properties by writing that type in brackets in the class definition line.

Applying Generics we could strictly specify the type of the association between a view and its controller as in the code below:

C#
public class ProductsView : WebFormView<ProductsController>, IProductsView
    ...
    private void ShowProductDetailsButton_Click(object sender, EventArgs e)
    {
        Controller.ShowProductDetails(); // typecasting NOT required

    }

To make the above code workable we need to extend our framework, adding the generics support.

Solution Implementation

First of all we will add a generic view and controller interfaces to the framework. They will extend old IView and IController interfaces with new strongly typed generic associations:

C#
public interface IView<T> : IView where T : IController
{
    new T Controller
    {
        get;
        set;
    }
}
public interface IController<TTask, TView> : IController where TTask : ITask
{
    new TTask Task
    {
        get;
        set;
    }

    new TView View
    {
        get;
        set;
    }
}

These interfaces alone do provide strongly typed associations, however, we also need to write some base generic implementation classes for these interfaces. So a developer will only inherit these base classes instead of implementing the interfaces above.

We will implement the properties simply with backing fields and mark them virtual so that a developer may override them in subclasses:

C#
public class WinFormView<T> : Form, IView<T> where T : class, IController
{
    ...
    protected T controller;

    public virtual T Controller
    {
        get { return controller; }
        set { controller = value; }
    }

    IController IView.Controller
    {
        get { return Controller; }
        set { Controller = value as T; }
    }
    ...
}
public class ControllerBase<TTask, TView> : IController<TTask, TView>
    where TTask : class, ITask
    where TView : class

{
    protected TTask task;
    protected TView view;

    public virtual TTask Task
    {
        get { return task; }
        set { task = value; }
    }

    public virtual TView View
    {
        get { return view; }
        set { view = value; }
    }

    ITask IController.Task
    {
        get { return Task; }
        set { Task = value as TTask; }
    }

    IView IController.View
    {
        get { return View as IView; }
        set { View = value as TView; }
    }
}

Note that the non-generic IView and IController interfaces are implemented as gateways to the strongly typed generic properties. This makes the access in the old non-generic manner (as done by the framework) equivalent to accessing the new strongly typed properties.

Below is an example of using the new generic features of the framework:

C#
class MyController : ControllerBase<MyTask, IMyView>

{
    public void MyOperation()
    {
        View.MyViewOperation(); // Typecasting to IMyView NOT required
    }

    public override MyTask Task
    {
        get { return base.Task; }
        set

        {
            base.Task = value;
            // Controller initialization here
            ...
        }
    }
}

Summary

In the article we have developed new framework features which make it more usable and allow us to avoid typecasting errors.

Project Website

www.MVCSharp.org

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)


Written By
Team Leader
Russian Federation Russian Federation
Oleg Zhukov, born and living in Russia is Lead Engineer and Project Manager in a company which provides business software solutions. He has graduated from Moscow Institute of Physics and Technology (MIPT) (department of system programming) and has got a M.S. degree in applied physics and mathematics. His research and development work concerns architectural patterns, domain-driven development and systems analysis. Being the adherent of agile methods he applies them extensively in the projects managed by him.

Comments and Discussions

 
-- There are no messages in this forum --