When you think ASP, think...
Recent Articles
All Articles
ASP.NET Articles
ASPFAQs.com
Message Board
Related Web Technologies
User Tips!
Coding Tips
Search

Sections:
Book Reviews
Sample Chapters
Commonly Asked Message Board Questions
JavaScript Tutorials
MSDN Communities Hub
Official Docs
Security
Stump the SQL Guru!
Web Hosts
XML
Information:
Advertise
Feedback
Author an Article
Jobs

ASP ASP.NET ASP FAQs Message Board Feedback ASP Jobs
 
Print this Page!
Published: Tuesday, November 4, 2003

Understanding Interfaces and Their Usefulness

By Tim Stall


Introduction


Many large Web applications in existence make use of User Controls, which are a unit of user interface reuse in ASP.NET. Common UI pieces - such as menus, page headers or footers, and so on - can be easily encapsulated into a User Control for reuse on numerous other pages. In their simplest form, User Controls are statically added to a Web page, dragged on from the Solution Explorer in Visual Studio .NET. However, User Controls can also be dynamically added to a page, a technique commonly used for providing customized user interfaces.

When multiple developers start building a large scale ASP.NET application that utilizes dynamically-added User Controls, the site's design often suffers from two common problems:

  1. Quality control, and
  2. Flexibility
One reason quality control suffers is because it is natural for developers to give the functionality of their components different method names. For example three developers creating similar components may opt to name related functions with different names. Second, flexibility will suffer unless there is a convenient way to reference dynamically called components. For example, imagine a particular ASP.NET page loads a set of User Controls specified through querystring values. Once these controls have been loaded, they each might have differently named methods or properties that need to be called/set. With a gaggle of different User Controls that could be loaded, and each with different method and property names, the page's source code will quickly become unreadable.

It is possible, though, to solve these quality control and flexibility issues through the use of .NET interfaces. This article explores how to use interfaces to simplify development of a site with dynamically loaded User Controls. (This article does not provide an in-depth look at User Controls or at techniques for dynamically loading Web controls. For more information on these topics be sure to read An Extensive Examination of User Controls and Dynamic Controls in ASP.NET.)

- continued -

Working with Dynamic User Controls - The Non-Interface Solution


In order to fully understand the benefits of using interfaces when building a Web application that uses dynamically-loaded User Controls, let's first look at an example of not using interfaces. Assume that we have a page that loads one of three User Controls based upon the querystring, and that later on in the code we need to read the value of a property. If each control has a different name for the property that we want to call, we'll need to determine what control was loaded and then read its appropriate property. There are a number of ways this could be accomplished, but they all boil down to a series of conditional statements, like:

// Determine what User Control was loaded based on the querystring value
string strSection = Request.QueryString["Section"];

string str = "";

// Use a switch statement to reference the correct User Control
switch (strSection) 
{
	case "A":
		str = ((NoneA)this.PlaceHolder1.Controls[0]).ControlData;
		break;
	case "B":
		str = ((NoneB)this.PlaceHolder1.Controls[0]).Values;
		break;
	case "C":
		str = ((NoneC)this.PlaceHolder1.Controls[0]).SelectedItems;
		break;
}; //end of switch-case

As the above example shows, one of three User Controls - NoneA, NoneB, or NoneC - has its appropriate property read, based on the querystring value. By inspecting the code you'll likely find a number of limitations that could be remedied:

  • Each control has a different property name for the same functionality (ControlData vs. Values vs. SelectedItems)
  • Reading the appropriate property requires a switch statement that has one section for each different type of control to be loaded. If there were many types of User Controls that might be loaded, the switch statement could quickly become tediously long and unreadable.
  • The possible User Controls are hard-coded into the switch statement, so we would need to modify the code if a new type of User Control could be added.
These limitations are inherent because we are not using interfaces. In the next section we'll see how interfaces give us the best of both worlds by easily solving the aforementioned problems and providing quicker User Control development time.

An Overview on Interfaces


Interfaces are a common concept in object-oriented programming. From the Java documentation:
In English, an interface is a device or a system that unrelated entities use to interact. According to this definition, a remote control is an interface between you and a television set, the English language is an interface between two people, and the protocol of behavior enforced in the military is the interface between people of different ranks. Within [an object-oriented] ... programming language, an interface ... is a device that unrelated objects use to interact with each other. An interface is probably most analogous to a protocol (an agreed on behavior). ...

You use an interface to define a protocol of behavior that can be implemented by any class anywhere in the class hierarchy. Interfaces are useful for the following:

  • Capturing similarities among unrelated classes without artificially forcing a class relationship.
  • Declaring methods that one or more classes are expected to implement.
  • Revealing an object's programming interface without revealing its class.
.NET provides an interface type that you can use to formally spell out a list of member signatures. Any class that implements an interface, must implement the list of member signatures defined by the interface. This assists quality control by enforcing the class members to use the same names. It also assists flexibility by providing interface polymorphism, which is similar to polymorphism with base classes.

Writing an interface is quick and easy, as the code below shows:

using System;

namespace Demo.WithInterfaces
{
	/// <summary>
	/// Summary description for ISection.
	/// </summary>
	public interface ISection
	{
		string GetData { get; }
	
		void ClearFields();

	} //end of interface
} //end of namespace

This code creates an interface named ISection. Notice how just like regular class files, an interface starts with the namespaces it uses, and can itself be wrapped in a namespace. However it differs from a class by using the interface keyword instead of the class keyword, and by having a body that is only a list of signatures without any actual implementation. This particular interface declares a read-only property named GetData that returns a string, and a method ClearFields().

Although an interface is similar to a base class, it is also very different. They are similar in that:

  • Both provide structure to another class that uses them
  • Both can be used for polymorphism
Interfaces are different than base classes in that:
  • A class can inherit only one base class, but it can implement many interfaces
  • A base class can contain implementation, an interface cannot
  • Interfaces can only contain Methods, Properties, Indexers, and Events. They cannot contain fields or constants (which are used for implementation)
Also, as Microsoft's Krzysztof Cwalina points out in his blog entry API Design Myth: Interface as Contract, interfaces don't specify a contract. Rather, they simply specify the syntax. If you want to guarantee semantics, you need to use a base class.

Dynamically-Loaded User Controls - The Interface Solution


Once you have created an interface, the next step is to have your User Controls implement the interface. To specify that a class must implement a particular interface use the following syntax:

// C#
public class ClassName : Interface

-- or, the class is derived from a base class --

public class ClassName : BaseClass, Interface

To have your User Control implement the ISection interface, go to the User Control's code portion and modify the class declaration so that it implements the interface:

public class WithA : System.Web.UI.UserControl, ISection

If you are using Visual Studio .NET, once you enter this code you'll see a tooltip pop-up that prompt you to press TAB in order to automatically create the stub of the interface, as shown in the screenshot below.

Press TAB, and you'll see the following code created:

#region ISection Members

public string GetData
{
	get
	{
		// TODO:  Add WithA.GetData getter implementation
		return null;
	}
}

public void ClearFields()
{
	// TODO:  Add WithA.ClearFields implementation
}

#endregion

If you try changing the names of this property or method, or remove the property or method, you'll get a compile-time error since not all of the interfaces members will be implemented in the class. By having all of our User Controls that can be dynamically loaded implement this common interface we'll have achieved one of our goals – to have the compiler enforce standardized names of methods and properties across all controls.

Recall that without interfaces, calling a method from the dynamically-loaded control required a switch structure that hard-coded each possible option. For each option we had to individually select the specific User Control's property. Also, the IntelliSense feature in Visual Studio .NET would show us all of the properties of each individual User Control, as shown in the screenshot below:

When using interfaces, however, our switch statement disappears. Instead, we can reference the dynamically-loaded User Control as an ISection and access the appropriate property with one line of code:

string strSectionData = ((ISection)this.PlaceHolder1.Controls[0]).GetData;

Furthermore, the IntelliSense in Visual Studio .NET shows just those property and methods for the ISection interface.

Besides these coding benefits, we're able to develop the application faster with interfaces because:

  • Visual Studio .NET automatically generates the interface stubs in our User Controls
  • Calling the controls only requires one line of code as opposed to a large switch statement (which needs to be updated whenever new controls that might be dynamically added are created or when method names change)
  • Method names for similar functions are guaranteed to be the same, making it quicker to become familiar with the application's API

Conclusion


Interfaces can be used at every tier of an enterprise application. While this article specifically provides an example in the presentation layer, you can benefit from interfaces at the business or data-access layers as well. Furthermore the .NET Framework itself extensively uses interfaces. Some of the common ones are for:
  • Different data providers - IDataReader, IDbConncetion, IDbDataAdapter, IDbTransaction
  • Collections - IDictionary, ICollection, IEnumerator, IEnumerable, and
  • Serialization (ISerializable), among many others
Interfaces provide a great tool for solving the common problems of quality assurance and flexibility. Not only are they easier and quicker to develop with, they're also common throughout the rest of the .NET Framework. A solid understanding of interfaces will benefit your applications at every level.

Happy Programming!

  • By Tim Stall


    Attachments


  • Download the demo (in ZIP format)

    About the Author


    Tim Stall is a Chicago-based technical consultant for Computer Sciences Corporation (www.csc.com), a global IT services company.



  • ASP.NET [1.x] [2.0] | ASPMessageboard.com | ASPFAQs.com | Advertise | Feedback | Author an Article