Sunday, July 22, 2012

Create a ComboBox web control with jQuery and ASP.NET


Introduction

ComboBox is a very common control that has no built-in support in HTML specification and in standard ASP.NET web control library, so the solution is to create one with JavaScript and wrapped up in ASP.NET custom control. You can use plain JavaScript to clip basic HTML elements into ComboBox, but it is very difficult to write, maintain, and support different browser. With the help of jQuery JavaScript library, this job becomes much easier.

Requirements

The ComboBox web control I am looking for must meet following requirements:
1. Support bind data through standard data-bound properties and methods
There are data-bound properties and methods defined by .NET component specification to separate source data with binding logics. By complaint with this convention, ComboBox web control can be easily understand and used in any data binding scenario.
2. Allow select item from the dropdown list of ComboBox with mouse
3. Allow enter data in the textbox of ComboBox and use it to filter items in dropdown list, and then select expected item with keyboard

Create a web control

To let ComboBox web control can be used in ASP.NET web application, we will create it as a custom web control. Because ComboBox behaves similar to the combination of TextBox and DropDownList, so it’s better to inherit it from both TextBox and DropDownList. Unfortunately, C# doesn’t permit multi-inheritance, so we can only choose one as the base class. Due to the most important character of ComboBox is allowing user directly entering data in it, so I decided to let it inherit from TextBox. In the meantime, I implemented DataSource, DataSourceID, DataMember properties and DataBind method in ComboBox to support data binding usage though it’s not the subclass of standard DataBoundControl. Those data binding properties and methods will forward the call to internal DropDownList control. By doing this, I don’t need to spend much effort on writing data binding code. The internal DropDownList control that ComboBox contains is only used as storage for dropdown list items. ComboBox corresponding JavaScript file, ComboBox.js, will use those data for client rendering.
During the OnPreRender stage, ComboBox outputs ComboBox.js JavaScript file into client browser. ComboBox.js is the file contains all of client side logics.
During the Render stage, ComboBox creates a HTML block with basic HTML elements to represent client side ComboBox, later on, JavaScript code in ComboBox.js clips generated HTML elements into looking and behavior what we want.

ComboBox HTML block

ComboBox HTML block is like this
<span style="position:relative;" ComboBox="1" >
 <input name="ComboBox1" type="text" value="Item 2" id="ComboBox1" class="textbox" style="width:200px;" />
 <input type="button" value="V" />
 <select name="ctl02" tabindex="-1" style="display:none;">
  <option selected="selected" value="Item 1">Item 1</option>
  <option value="Item 2">Item 2</option>
  <option value="Item 3">Item 3</option>
 </select>
 <div style="visibility:hidden; background-color:white"></div>
</span>
The outermost element is SPAN. It is used to contain all other elements for ComboBox control in HTML. There is a custom attribute ComboBox on it to flag SPAN as ComboBox container markup. And then a Text input element inside of SPAN is used to represent the textbox that user can enter data in ComboBox. The next element is a Button input that is used to represent the button of ComboBox. It uses “V” as button icon to distinguish with the built-in HTML select element. The following element is a Select that is used to store download list items. At the end, DIV is included in ComboBox to represent dropdown list of ComboBox. Despite nothing is initially contained in DIV, the bootstrap code in ComboBox.js will add a table into it and make it look and behave like a dropdown list.

ComboBox.js

This JavaScript file contains all logics for building up ComboBox in browser. Here I gave more detail explanation on purpose of each routing and method in ComboBox.

Initialize ComboBox (Bootsrapping)

After completed DOM rendering, bootstrapping code in ComboBox.js will go through below steps to initialize ComboBox:
1. Find all ComboBoxes on the page
2. Initialize each ComboBox by calling ComboBox_InitListData inside of jQuery .each API
3. Add click event handler for ComboBox’s dropdown button, “V” button
4. Add keydown and keyup event handler for ComboBox’s textbox
5. Add click event handler for document, so ComboBox’s dropdown list can be hidden when user click on anywhere other than ComboBox’s dropdown button
//initialize all ComboBoxes after DOM is fully loaded
$(function () {
    var $comboBoxs = $("span[ComboBox]"); //get all ComboBoxes. ComboBox is defined with span element that has ComboBox attribute

    //init each ComboBox with empty filter
    $comboBoxs.each(function (i, obj) {
        ComboBox_InitListData($(obj), "");
    });

    //add click event handler for ComboBox "V" button
    $comboBoxs.find(":button").on("click", function (e) {
        ComboBox_HideList(); //hide all ComboBoxes' dropdown list first

        var $container = $(this).closest("span"); //get the first element that matches the "span" selector, beginning at the current element and progressing up through the DOM tree
        ComboBox_InitListData($container, ""); //init ComboBox with empty filter
        $container.find("div").css({ "zIndex": "1", "visibility": "visible" }); //set css of div on zIndex and visibility
        e.stopPropagation(); //prevents the event from bubbling up the DOM tree, preventing any parent handlers from being notified of the event
    });

    //Set TextBox attribute and add keydown and keyup event handler for ComboBox textbox
    $comboBoxs.find(":text")
              .data("currentitem", -1) //current selected item is -1
              .attr("autocomplete", "off") //turn off auto complete
              .on("keydown", function (e) { //set keydown event handler
                  ComboBox_KeySelectItem(e);
              })
              .on("keyup", function (e) { //set keyup event handler
                  ComboBox_KeyFilterItem(e);
              });

    //add click event handler for document
    $(document).click(function (e) {
        var element = e.srcElement || e.target;
        if (element != undefined && element.tagName == "INPUT" && element.value == "V") {
            //when click on the ComboBox "V" button, then do nothing (note: event handler on "V" button will handle this event)
        }
        else {
            //when click on somewhere else, then hide all ComboBoxes' dropdown list
            ComboBox_HideList();
        }
    });
});

Initialize List Data

Initialize list data method creates a table inside DIV to show as a dropdown list, this is done by first find DIV in ComboBox, and then create an in memory table to hold all item from Select element. At the end, put table into ComboBox DIV and hide it up.
//init combobox items
function ComboBox_InitListData($container, filterValue) {
    var $div = $container.find("div");
    var newList = new Array();
    var oSelect = $container.find("select")[0];
    var len = oSelect.options.length;

    for (var i = 0; i &lt len; i++) {
        if (filterValue == undefined || filterValue == "") {
            newList[newList.length] = oSelect.options[i].text;
        }
        else {
            if (newList.length >= 9) {
                break;
            }
            var currVal = oSelect.options[i].text;
            if (currVal.length >= filterValue.length) {
                if (currVal.toLowerCase().substring(0, filterValue.length) == filterValue.toLowerCase()) {
                    newList[newList.length] = currVal;
                }
            }
        }
    }

    var sHtml = [];
    sHtml.push("<table border=\"0\" cellpadding=\"0\" cellspace=\"0\" width=\"100%\" border=\"1\" style=\"z-index:10; background-color:white;\">");
    for (var i = 0; i < newList.length; i++) {
        sHtml.push("<tr onMouseOver=\"this.bgColor='#191970'; this.style.color='#ffffff'; this.style.cursor='default'; \" onMouseOut=\"this.bgColor='#ffffff'; this.style.color='#000000';\">");
        sHtml.push("<td nowrap onClick=\"ComboBox_SelectItemWithMouse(this);\">");
        sHtml.push((newList[i] == "" ? " " : newList[i]));
        sHtml.push("</td>");
        sHtml.push("</tr>");
    }
    sHtml.push("</table>");

    $div.html(sHtml.join('')); //set the HTML contents of div to concatenated string from sHtml arrary

    $div.css("overflowY", "auto"); //oTmp.style.overflowY = "auto";
    $div.css("border", "1px solid midnightblue"); //oTmp.style.border = "1px solid midnightblue";
    $div.css("position", "absolute"); //oTmp.style.position = "absolute";
    $div.css("visibility", "hidden"); //oTmp.style.visibility = "hidden";

    var count = $container.find("table td").size(); //get total ComboBox items
    var $text = $container.find(":text"); //get textbox element
    var $button = $container.find(":button") //get button element
    $div.css("width", $button.outerWidth() + $button.offset().left - $text.offset().left); //make the dropdown list same width as textbox + "V" button
    if (count > 7 || count == 0) {
        $div.css({ "height": "150" }); //limit the height of dropdown list when there is more than 7 items or default the height of dropdown list when there is no item
    }
    else { 
        $div.css({ "height": count * 21 }); //set the height of dropdown box same as total of items' height. Each item's height is 21
    }
}

Hide List

ComboBox dropdown list should not visible when user is working on other part of the page. This is the common behavior of a Select element in HTML. By find all ComboBoxes’ dropdown list container, DIV element, and set it as hidden with CSS will make all ComboBoxes’ dropdown list invisible.
//hide ComboBox dropdown list
function ComboBox_HideList() {
    $("span[ComboBox]").find("div").css("visibility", "hidden");
}

Is List Hidden

In most cases, ComboBox behave differently based on whether dropdown list is visible, so this method is used to provide visibility status of the dropdown list.
//is ComboBox dropdown list hidden
function ComboBox_IsListHidden($container) {
    return $container.find("div").css("visibility") == "hidden";
}

Set Item in Dropdown List

Every time, a key is pressed, ComboBox will try to handle Up, Down, Enter, and Escape key to select an item in Dropdown List. This makes dropdown list of ComboBox behave same with dropdown list of Select.
//keydown
function ComboBox_KeySelectItem(e) {
    var txt = e.srcElement || e.target;
    var currentitem = $(txt).data("currentitem");
    var val = $.trim($(txt).val()); //get value in textbox
    var $container = $(txt).closest("span[ComboBox]"); //get ComboBox container that is defined with span element and ComboBox attribute

    var key = e.keyCode || e.which; //get key code
    switch (key) {
        case 38: //up
            if (val == "" || ComboBox_IsListHidden($container)) {
                return;
            }
            --currentitem;
            $(txt).data("currentitem", currentitem);
            ComboBox_ChangeItemWithKey(txt);
            break;
        case 40: //down
            if (val == "" || ComboBox_IsListHidden($container)) {
                return;
            }
            currentitem++;
            $(txt).data("currentitem", currentitem)
            ComboBox_ChangeItemWithKey(txt);
            break;
        case 13: //enter   
            if (!ComboBox_IsListHidden($container)) {
                ComboBox_HideList();
                return false;
            }
            break;
        case 27: //esc
            ComboBox_HideList();
            return false;
            break;
        default:
            break;
    }
}

Reset Dropdown List

After a key gets released, the dropdown list should be reset to match with the entered text in textbox.
//keyup
function ComboBox_KeyFilterItem(e) {
    var txt = e.srcElement || e.target;

    //do nothing if up, down, enter, esc key pressed
    if (e.keyCode == 38 || e.keyCode == 40 || e.keyCode == 13 || e.keyCode == 27) {
        return;
    }

    $(txt).data("currentitem", -1);
    var val = $(txt).val();
    if (val == "") {
        ComboBox_HideList();
        return;
    }

    var $container = $(txt).closest("span[ComboBox]");
    ComboBox_InitListData($container, val);

    var $div = $container.find("div");
    $div.css({ "zIndex": "1", "visibility": "visible" });

    //hide dropdown list if there is no item
    if ($div.find("td").size() == 0) {
        ComboBox_HideList();
    }
}

Change Item

When current item is changed, ComboBox will toggle color of text and background to make the current item appear as highlighted.
//change item
function ComboBox_ChangeItemWithKey(txt) {
    var $txt = $(txt);
    var currentitem = $txt.data("currentitem");
    var table = $txt.closest("span[ComboBox]").find("table")[0];

    for (i = 0; i < table.rows.length; i++) {
        table.rows[i].bgColor = "#ffffff";
        table.rows[i].style.color = "#000000";
    }
    if (currentitem < 0) {
        currentitem = table.rows.length - 1;
    }
    if (currentitem == table.rows.length) {
        currentitem = 0;
    }
    $txt.data("currentitem", currentitem);

    if (table.rows[currentitem] == null) {
        ComboBox_HideList();
        return;
    }
    table.rows[currentitem].bgColor = "#191970"; //darkblue color
    table.rows[currentitem].style.color = "#ffffff"; //whit color
    $txt.val($(table.rows[currentitem].cells[0]).text());
}

Select Item

The dropdown list item can be either selected with mouse or keyboard, after an item is selected, the value of selected item will be assigned to textbox and dropdown list will be closed.
//select item
function ComboBox_SelectItemWithMouse(td) {
    var $div = $(td).closest("div");
    var $txt = $div.parent().find(":text");
    var selectedValue = $(td).text();
    if ($.trim(selectedValue) == "") {
        selectedValue = "";
    }
    $txt.val(selectedValue);
    $txt[0].focus();
    $div.css("visibility", "hidden");
}

jQuery 1.7 attaching event handler API

The ComboBox uses new attaching event handler API, .on() method, of jQuery 1.7 to define event handler. The .on() method is the preferred method for attaching event handlers to an element. Users of older versions of jQuery should use .delegate() in preference to .live().

$(selector).live(events, data, handler); // jQuery 1.3+
$(document).delegate(selector, events, data, handler); // jQuery 1.4.3+
$(document).on(events, selector, data, handler); // jQuery 1.7+ 

How to use ComboBox

After referenced custom web control assembly in Visual Studio project, the simplest way to use ComboBox is just drag it from toolbox into ASP.NET web page.


By drop it into ASPX page, Visual Studio will automatically generate markup for ComboBox
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="Demo.Web.Default" %>

<%@ Register assembly="Demo.WebControls" namespace="Demo.WebControls" tagprefix="cc1" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script type="text/javascript" src="Scripts/jquery-1.7.2.js"></script>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <cc1:ComboBox ID="ComboBox1" runat="server"></cc1:ComboBox>
    </div>
    </form>
</body>
</html>
Add some code-behind code to bind ComboBox with a List collection.
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                List<string> data = new List<string>();
                data.Add("Item 1");
                data.Add("Item 2");
                data.Add("Item 3");
                ComboBox1.DataSource = data;
                ComboBox1.DataBind();
            }
        }
This is what ComboBox looks like on screen

Summary

With the help of jQuery, we can combine those basic HTML elements into a more complicate client side component – ComboBox.

Tuesday, May 15, 2012

How to troubleshoot ASP.NET application hang with memory dump


Introduction

A production IIS server has been reported hang once a day. We tried every possible ways to find and remedy the situation with no luck. Fortunately, from memory dump, we found some clues that eventually pinpoint the source of problem. In here, I will put all the information and experience I got from the process of capturing and analyzing memory dump.

The environment

This is an ASP.NET 2.0 based web application that is running in Windows 2008 server and use SQL Server 2008 as database. The web application is dealing with documents heavily. All documents are stored in a dedicated document server. All the servers are VMWare based virtual server.

The problem

In last several months, our client start to experience server hang occasionally. When the server hangs, nobody can use the web application and system administrator can’t even remote into the server. In the beginning, we checked server configuration, software installed, processes are running, application source code, event viewer, IIS log, etc to try find some clue. Unfortunately, there is nothing unusual. So, we start to focus on finding a way to gather more information when IIS hang happening. The idea is to capture IIS memory dump during server hang and use memory dump tool to understand what’s happening at that moment.

Tools

In order to get memory dump during server hang happening, we need following tools.

Windows Debugging Tool

Windows debugging tool can be obtained from Microsoft’s Download and Install Debugging for Windows page (http://msdn.microsoft.com/en-us/windows/hardware/gg463009). The Windows Software Development Kit (SDK) for Windows 8 Consumer Preview is the one contains latest windows debugging tool.

After installed Windows Software Development Kit for Windows 8 Consumer Preview, you will have a Windows Kits folder in C:\Program Files (or C:\Program Files (x86) in 64 bit Windows). Don’t gets confused this with Windows SDK folder that could already exists in your C:\Program Files (or C:\Program Files (x86) in 64 bit Windows). There are many tools in Windows Kits. What we gonna to use are:
(1) cdb.exe
A user-mode debugger with a console interface. This will be used later in memory dump capturing script.
(2) windbg.exe
A user-mode and kernel-mode debugger with a graphical interface. This will be used to analyze captured memory dump.

Debug Diagnostic Tool v1.2

The Debug Diagnostic Tool (DebugDiag) is designed to assist in troubleshooting issues such as hangs, slow performance, memory leaks or memory fragmentation, and crashes in any user-mode process. This tool includes additional debugging scripts focused on Internet Information Services (IIS) applications, web data access components, COM+ and COM+ related Microsoft technologies, SharePoint, and .NET framework. What we really needed from Debug Diagnostic Tool is those debugging extensions for windbg.

How to setup sever hang memory dump capturing

Our client’s server is Windows Server 2008 that has IIS 7 come with it. Follow below steps can setup a trigger for generating memory dump when IIS hang.

1. Create a GenerateDump.bat batch file

The batch file contains following script
@if "%_echo%"=="" echo off
setlocal
    set TIMESTAMP=%DATE:~-9%_%TIME%
set TIMESTAMP=%TIMESTAMP:/=_%
set TIMESTAMP=%TIMESTAMP::=_%
set TIMESTAMP=%TIMESTAMP:.=_%
set TIMESTAMP=%TIMESTAMP: =_%
set FILENAME=c:\crash_PID_%1_%TIMESTAMP%.dmp
set LOG=c:\log.txt
set COMMAND= C:\Program Files (x86)\Windows Kits\8.0\Debuggers\x64\cdb.exe -c ".dump /o /ma %FILENAME%;q" -p %1

echo %COMMAND% > %LOG%
%COMMAND%

endlocal

2. Configure the Orphan Worker Process Settings

(1) In command window, go to adminscripts folder of inetpub
cd c:\inetpub\adminscripts
(2) To enable the orphan worker process feature, type the following command at the command prompt
adutil.vbs SET W3SVC/AppPools/DefaultAppPool/OrphanWorkerProcess TRUE
(3) At the command prompt, set the batch script in step 1 to run when a process is scheduled to be recycled.
adsutil.vbs SET W3SVC/AppPools/DefaultAppPool/OrphanActionExe “c:\GenerateDump.bat”

adsutil.vbs SET W3SVC/AppPools/DefaultAppPool/OrphanActionParams “%1%”
Note: Make sure that the OrphanActionExe option points to the location of the batch file that was created above and make sure the account of w3wp.exe process has Read and Execute permissions to that file.

How to analyze memory dump

After a dump file is captured during IIS hang, we use windbg to open up the dump file

Load memory dump into windbg

(1) Open up windbg


There are x86 version windbg and x64 version windbg. Which one to run not depends on your development machine’s Windows version, it depends on your memory dump machine’s Windows version. Based on the version of windbg you run, you need to load corresponding debugging extensions in following steps.

(2) Go to File -> Open Crash Dump. Choose the dump file captured by your IIS server.


(2) Run command
!symfix

This command will automatically set the symbol path to Microsoft’s symbol store. By doing this, you must have Internet connection available. Alternatively, you can download symbols to your local in advance or just directly point to Microsoft’s symbol server with syntax like this
srv*c:\symbols*http://msdl.microsoft.com/download/symbols


Load additional debugging extensions

The built-in command of windbg provides limited analysis functionality for managed memory dump, so you need some debugging extensions to help reveal more information inside managed memory dump
(1) Run command
!load psscor2
Psscor2 is a part of Debug Diagnostic Tool. It is a managed debugging extension of windbg. It’s designed to debug ASP.NET 2.0 and 3.5 memory dump. You can also load Psscor4 into windbg if want to debug ASP.NET 4.0 application memory dump. Psscor2 is a superset of debugging extension sos. By loading this debugging extension into windbg, we don’t need sos debugging extension anymore.
If you load psscor2 failed because can’t find correct version mscordacwks, then you can use
.cordll –ve –u –I mscorwks –l 
to load the correct one. The cordll command will try to find the correct mscorwks from several different locations and tells you whether those attempting success or not.


(2) Run command
!load IISInfo
IISInfo debugging extension is also a part of Debug Diagnostic Tool. It’s used to show IIS and ASP information in memory dump


Analyze memory dump with debugging commands

(1) Run command
.time
This is a windbg built-in command. It’s used to display system up time, process up time, kernel time, and user time.


(2) Run command
!aspxpages
This is a command from psscor2 debugging extension. It is used to list which ASP.NET pages are being processed in which threads.


(3) Run command
!Threads 
It is a command from psscor2 debugging extension. It is used to list all running threads in memory dump


(4) run command
~[Thread Id]s
It is a command from psscor2 debugging extension. It is used to select specific thread


(5) run command
!CLRStack –p
It’s a command from psscor2 debugging extension. It is used to show the current selected thread’s CLR stack trace with parameter information


(6) Run command
!do [memory address]
It’s a command from psscor2 debugging extension. It is used to reveal content in specified memory address.


(7) Run command
!dae
This is a command from psscor2 debugging extension. It is used to dump all .NET exceptions found in your memory dump.


(8) Run command
!threadpool
It’s a command from psscor2 debugging extension. It is used to find out exactly what the CPU usage was at the time the dump was taken. We’ll also get some useful information like the number of work requests in the queue, completion port threads and timers.


(9) Run command
!clientconns
It’s a command from IISInfo debugging extension. It’s used to see all client connections.



The finding

From memory dump, we found long running process is trying to get document from client’s document server, however, because document server doesn’t response promptly to the request, ASP.NET process just hang in there waiting and waiting. This kind of document request is keep coming in, so finally, all hang document request process brought down the IIS server.

Summary

Windows Debugging Tool is a very useful tool on dealing with complicate application problem in Windows. For my case, IIS hang is a bizarre problem to us as application developer. With memory dump and memory dump analysis tool, we can gather more information and pinpoint the problem.

Saturday, April 7, 2012

Build a Pluggable Application with IoC Container


Introduction

When we build an application, we always face a lot of changes during and after application development. To be ready for changes in advance is a key character of a flexible application. IoC container stands for Inversion of Control container. It is used frequently in situation of we don’t want to directly hardcode the logic of instantiate an implementation of contract/interface in our application. By following contract first design principal and relay the instantiation responsibility to IoC container, we can create an extensible and flexible application.

Demo application

Suppose we want to design an application that can output text to different output channel, such as file output channel and console output channel. What we can do first is to define an output contract, so the main application will follow the contract to output text without knowing specific output channel.
public interface IOutputService
{
    void WriteLine(string data);
}
After we have the contract defined, we can have two different implementations as file output channel and console output channel:
FileOutput:
public class FileOutput: IOutputService
{
    public void WriteLine(string data)
    {
        using (StreamWriter sw = new StreamWriter("test.txt", false))
        {
            sw.WriteLine(data);
        }
    }
}
ConsoleOutput:
public class ConsoleOutput: IOutputService
{
    public void WriteLine(string data)
    {
        Console.Write(data);
    }
}
The easiest way to get an output channel in application is to have a channel factory that will create an instance of requested output channel. However, by doing this, we hardcode the instantiation logic inside our application. If we want to add a new output channel, such as network output channel, then our only opinion is to change the code.

Make the demo application pluggable

With the help of IoC container, we can easily create a pluggable application without much coding. The idea is to define a base library that will have API like this:
public interface IIoCContainer
{
    T Resolve<t>();
    IEnumerable<t> ResolveAll<t>();
}
This API gives application a way to retrieve a single instance or a collection of instances of specified type, so you can use the IOutputService interface to get a specific output channel. The IoC container API allows us to use any IoC container, such as Unity or StructureMap. At the moment of application starting up, we use BootStrapper to setup IoC container.
BootStrapper:
public class BootStrapper
{
    public static void StartUp()
    {
        RegisterIoCContainer();
    }

    private static void RegisterIoCContainer()
    {
        ObjectFactory.Initialize(x => { x.PullConfigurationFromAppConfig = true; });
        IoC.IoCContainerManager.IoCContainer = new StructureMapIoCContainer();
    }
}
Initialize IoC container with BootStrapper.
BootStrapper.StartUp();
After IoC container is initialized, application can directly use IoC container API to get IOutputService.
IEnumerable<ioutputservice> outputServices = IoC.IoCContainerManager.IoCContainer.ResolveAll<ioutputservice>();
outputServices.ToList().ForEach(o => o.WriteLine("Hello World!"));
In order to make our application more flexible and allow us to switch different output channel in production environment without recompilation, I decided to not directly reference output channel implementation in main application.
The output channel implementation will be copied into main application via Post-build event command line.
And the mapping between IOutputService and actual implementation is defined in application configuration file.
<configSections>
    <section name="StructureMap" 
      type="StructureMap.Configuration.StructureMapConfigurationSection,StructureMap"/>
</configSections>

<StructureMap>
    <PluginFamily Type="OutputService.IOutputService" 
             Assembly="OutputService" DefaultKey="Default">
      <Plugin Type="FileOutput.FileOutput" 
             Assembly="FileOutput" ConcreteKey="Default"/>
      <Plugin Type="ConsoleOutput.ConsoleOutput" 
             Assembly="ConsoleOutput" ConcreteKey="Console"/>
    </PluginFamily>
</StructureMap>

How the whole application works

When calling IoCContainer.ResolveAll<ioutputservice>(), the application will relay the call to IoC container, then IoCContainer will based on mapping in configuration file to get specific implementation.
After got a collection of IOutputService, then call WriteLine of IOutputService to write “Hello World” to every output channel.

Summary

With the help of IoC container, we can quickly implement a simple pluggable application. This pluggable application can utilize configuration file to add new implementation for defined contract without changing code.

Using the Code

The code is developed in Visual Studio 2010. You can create your own IOutputService implementation and add into configuration file to experiment with the demo application.