Jeremy D. Miller -- The Shade Tree Developer

Sponsors

The Lounge

Syndication

News

Advertisement

Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
Plugging UserControl's with StructureMap 2.0

By request, StructureMap 2.0 will finally allow you to use ASP.Net UserControl's for both Dependency Injection and Service Location.  Right now you have to use the programmatic interface to configure the UserControl's.  If there is demand, I'll add an Xml construct specifically for UserControl's.

Ok since this has been going around lately, let's say that you are building a new Model View Controller framework for ASP.Net (yes you could just use MonoRail or Igloo, but let me have my example).  The first thing you build is a FrontController class to handle all incoming requests, then select the requested instance of IPresenter to build the view.  Each IPresenter instance will have to expose an ASCX UserControl for the framework to render the actual html.  The FrontController class and the interface for IPresenter are shown below.

public class FrontController

{

    public void ProcessPage(PageRequest request)

    {

        // 1.) handle the request, and create the Model class

        // 2.) fetch the correct IPresenter

        IPresenter presenter = ObjectFactory.GetNamedInstance<IPresenter>(request.PageName);

        presenter.BuildView(request);

 

        this.writeView(presenter.View);

    }

}

 

public interface IPresenter

{

    object View { get;}

    void BuildView(PageRequest request);

}

In the most basic case I have a simple implementation of IPresenter named PagePresenter that uses and supervises a view represented by an IControl interface.

public interface IControl

{

    void SetName(string name);

}

 

public class PagePresenter : IPresenter

{

    private readonly IControl _control;

 

    public PagePresenter(IControl control)

    {

        _control = control;

    }

 

    public object View

    {

        get { return _control; }

    }

 

    public void BuildView(PageRequest request)

    {

        throw new NotImplementedException();

    }

}

Now, I want to make StructureMap push in the actual implementation of IControl so that I can easily change the view later on, or simply to make the wiring of the dependencies for me.  In the Global.asax file for the application I add the following code:

    void Application_Start(object sender, EventArgs e)

    {

        // Turn off configuration from StructureMap.config

        StructureMapConfiguration.UseDefaultStructureMapConfigFile = false;

 

        // Specify that the default implementation of IControl is TheControl.ascx

        StructureMapConfiguration.BuildInstancesOf<IControl>()

            .TheDefaultIs(

                Registry.LoadUserControlFrom<IControl>("TheControl.ascx"));

 

        // Add the named instance of IPresenter. 

        StructureMapConfiguration.AddInstanceOf<IPresenter>()

            .UsingConcreteType<PagePresenter>()

            .WithName("ThePage");

    }

 

The Fluent Interface is arguably more expressive and readable, but it comes at a cost of increased verbosity.  You might find it cleaner to break up the configuration declarations into separate pieces.  For that very purpose, there is a new class in StructureMap 2.0 called Registry that can be used to make programmatic additions to the StructureMap configuration.  You can either instantiate a Registry directly and pass it into StructureMapConfiguration.AddRegistry(Registry), or more powerfully, write your own like this one.

    public class ControlRegistry : Registry

    {

        // Little helper method

        private void registerView<T>(string url)

        {

            BuildInstancesOf<T>().TheDefaultIs(LoadControlFromUrl<T>(url));

        }

 

        protected override void configure()

        {

            registerView<IControl>("MyControl.ascx");

            // more calls to registerView

        }

    }

Now, we need to direct StructureMap to use our ControlRegistry.  Here's where it gets fun.  StructureMap has always had functionality to scan assemblies for classes or interfaces marked with StructureMap attributes.  As of 2.0 StructureMap is also looking in these assemblies for any public Registry subclasses with a no constructor arguments.  Finally, all we need to do is add the correct assemblies to StructureMap.   

            StructureMapConfiguration.AddRegistry(new ControlRegistry());

 

            // OR

 

            StructureMapConfiguration.ScanAssemblies().IncludeTheCallingAssembly();

 Assuming that the ControlRegistry class is in the assembly that is calling into StructureMapConfiguration, you're all set.  There are other methods on ScanAssemblies() to attach other assemblies.


Posted Wed, Apr 4 2007 6:10 AM by Jeremy D. Miller
Filed under:

[Advertisement]

Comments

inoodle wrote re: Plugging UserControl's with StructureMap 2.0
on Wed, Apr 4 2007 8:38 AM

Cheers Jeremy,

Just reading and inwardly digesting :)

Jeremy D. Miller wrote re: Plugging UserControl's with StructureMap 2.0
on Wed, Apr 4 2007 9:07 AM

Feel free to send any feedback in.  It's brand new, so there's no installed base to worry about if I need to change the way it's working.

Jeremy

Dave Newman wrote re: Plugging UserControl's with StructureMap 2.0
on Wed, Apr 4 2007 11:53 PM

Hey Jeremy, this looks pretty good.  I've retrofitted an MVC framework into a legacy app i'm working on, but I haven't gotten an IoC framework in yet to auto-wire dependencies.  Previously i've used Windsor, but I might give structuremap a go.  Sorry. haven't had much of a look into it, but does structure map have any built in nhibernate support? (transactions, opening and closing sessions on page requests)

Jeremy D. Miller wrote re: Plugging UserControl's with StructureMap 2.0
on Thu, Apr 5 2007 8:04 AM

Dave,

What do you have in mind?

I've used StructureMap in the past to help wire up NHibernate (the HttpContext, ThreadLocal, and Hybrid scoping were put in expressly for the way we were using NHibernate last year), but I don't have anything in StructureMap itself for NHibernate.  

I've been uncomfortable trying to put in some sort of generic support for NHibernate lifecycle directly into StructureMap because I've always been worried about coding in a strategy that isn't really generally applicable.

By and large, I've taken the attitude that StructureMap is mostly an IoC tool only, not an application stack.

inoodle wrote re: Plugging UserControl's with StructureMap 2.0
on Thu, Apr 5 2007 8:40 AM

Hi Jeremy,

I'll probably hold off for the moment, as I'm still not sure I should have a dependency on a DI framework! as I mention here: http://intrepidnoodle.com/blog/show/10.aspx

I think the solution might be to use StructureMap but to hide it with an abstraction which uses the programmatic configuration... (which I think you mentioned in a more recent post).

Jeremy D. Miller wrote re: Plugging UserControl's with StructureMap 2.0
on Thu, Apr 5 2007 8:43 AM

Or just steal that tiny bit of code out of StructureMap.  If all you wanted was a way to keep a registry of UserControl's, it wouldn't take much to code.

inoodle wrote re: Plugging UserControl's with StructureMap 2.0
on Thu, Apr 5 2007 10:44 AM

Thanks Jeremy, very kind of you. I'll drop you a line once I've put something together.

davidt64 wrote re: Plugging UserControl's with StructureMap 2.0
on Sat, Jan 12 2008 10:09 PM

Hello,

I've been starting to learn IoC principles by using StructureMap on a little project. I am trying to use the Registry class to perform some StructureMap configuration as outlined in this post. However, the configuration changes made in the configure() routines are somehow not "sticking"; that is, after configure() runs, ObjectFactory.WhatDoIHave doesn't show the changes, and retrieving an instance through ObjectFactory gives a "type not configured" error. I've tried using both ScanAssemblies and AddRegistry. Any idea what else I might try?

Thanks!

Jeremy D. Miller wrote re: Plugging UserControl's with StructureMap 2.0
on Sat, Jan 12 2008 10:22 PM

@davidt64,

Would you send me an email off of the contact up above?  I'll try to help

Add a Comment

(required)  
(optional)
(required)  
Remember Me?