Click here to Skip to main content
6,629,377 members and growing! (21,501 online)
Email Password   helpLost your password?
Development Lifecycle » Design and Architecture » Frameworks License: The Microsoft Public License (Ms-PL)

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

By Oleg Zhukov

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.
C#, .NET, Dev
Posted:25 Apr 2008
Views:7,554
Bookmarked:23 times
Announcements
Loading...
 
Search    
Advanced Search
Add to IE Search
printPrint   add Share
      Discuss Discuss   Broken Article?Report  
1 vote for this article.
Popularity: 0.00 Rating: 4.00 out of 5

1

2

3
1 vote, 100.0%
4

5

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:

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:

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:

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:

    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:

    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:

    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)

About the Author

Oleg Zhukov


Member
Oleg Zhukov, born and living in Russia is a software development consultant in a company which provides business 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.
Occupation: Architect
Location: Russian Federation Russian Federation

Other popular Design and Architecture articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
  (Refresh) 
-- There are no messages in this forum --

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 25 Apr 2008
Editor: Sean Ewington
Copyright 2008 by Oleg Zhukov
Everything else Copyright © CodeProject, 1999-2009
Web10 | Advertise on the Code Project