I’ve been playing around with Glimpse recently, and knowing that my favourite tech at the moment is the Managed Extensibility Framework (MEF), I decided to put together a Glimpse plugin that would allow you a glimpse (ahem) into what is going on inside your composition container. The plugin is implemented as a series of decorators around the primitive MEF types (currently we are concentraing on Catalogs), and a custom implementation of a CompositionContainer that supports the Glimpse mechanism.

How does it work?

At the core of the plugin, we have our custom container, the GlimpseCompositionContainer. This is a subclass of the standard CompositionContainer, it supports the ability to grab information about your catalogs. We do this during construction of the container by building a set of descriptors for the catalogs. So, the first step to get started (in fact, the only step), is to swap your declaration of your container to:

var catalog = new AggregateCatalog(
  new DirectoryCatalog("bin"));
  
var container = new GlimpseCompositionContainer(catalog);

The GlimpseCompositionContainer is designed to replace your current container. If Glimpse is not enabled, the container simply behaves like the standard CompositionContainer. When it is enabled, we decorate any of the catalogs using our GlimpseCatalog.

The GlimpseCatalog is responsible for providing details on the exports that are being required for composition. So for each requested contract, a set of possible definitions may be returned.

Getting this data to Glimpse

Because Glimpse is designed to display data to the client, data is collected through the lifetime of the request, and pushed down to client on render. We currently collect data in two places:

  1. Catalog information (presented on the MEF Container tab) displays the list of catalogs, and the parts available for each catalog. This is collected and stored in the runtime cache (as the container should essentially be declared once for the lifetime of the applicaiton.
  1. Import information (presented on the MEF Imports tab) displays the list of requests to the composition container, along with any matching exports. This is collected for each request, and is stored in the Request.Items collection.

With this information to hand, we can start visualising what our composition system is made of.

The sample Application

On the Github project I’ve built a sample project which demonstrates the sort of information we can start getting from our app. In the sample app, I’ve reused the MefDependencyResolver and MefControllerFactory from my previous MVC+MEF projects (see here) which gives us a quick demonstration of how it all works.

With a dependency resolver and a controller factory plugged in, we can start exporting our controllers:

namespace Glimpse.MEF.Sample.Controllers
{
    using System;
    using System.ComponentModel.Composition;
    using System.Web.Mvc;

    using Models;
    using Models.Logging;

    /// <summary>
    /// Defines the home controller.
    /// </summary>
    [ExportController("Home"), PartCreationPolicy(CreationPolicy.NonShared)]
    public class HomeController : Controller
    {
        #region Fields
        private readonly ILogger _logger;
        #endregion

        #region Constructor
        /// <summary>
        /// Initialises a new instance of <see cref="HomeController"/>.
        /// </summary>
        /// <param name="logger">The logger.</param>
        [ImportingConstructor]
        public HomeController(ILogger logger)
        {
            if (logger == null) throw new ArgumentNullException("logger");

            _logger = logger;
        }
        #endregion

        #region Actions
        /// <summary>
        /// Displays the default view.
        /// </summary>
        /// <returns></returns>
        public ActionResult Index()
        {
            _logger.Log("Entered HomeController.Index() action.");

            ViewBag.Message = "Welcome to ASP.NET MVC!";

            _logger.Log("Returning result from HomeController.Index() action.");
            return View();
        }

        /// <summary>
        /// Displays the about view.
        /// </summary>
        /// <returns></returns>
        public ActionResult About()
        {
            return View();
        }
        #endregion
    }
}

There is nothing really extensive going on here, I’ve just updated the the default HomeController implementation to support an injection of a dependency (our ILogger), and we then [Export] the controller so it can be picked up by MEF.

How does this get presented to Glimpse? Well, when we make a request to our /Home url, we started saving information about each request to GetExports on our catalogs. So in the above example, we resul in the followin items:

  1. Request to match contract System.Web.Mvc.IController which returns our 1 instance of our exported controller.
  2. Request to match contract GlimpseMEF.Models.Logging.ILogger which returns our 1 instance of our exported logger. This is then injected into our controller.

This is an initial version, which could change quite a lot, I need to detemine what sort of information people want to see. With that in mind, grab the source code, or search for Glimpse.MEF on Nuget to start playing around.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

Tags ___ ,