Using Unity in ASP .NET aspx page

May 12, 2008 at 12:18 PM
This article at http://www.codeproject.com/KB/aspnet/spring-asp.aspx shows how to use DI of spring in aspx pages and other objects. I could not find any way to do that in Unity. Any help?
May 12, 2008 at 6:54 PM
Edited May 12, 2008 at 7:41 PM
I made a very simple Unity integration sample with ASP.NET page.
Please see the Unity Contrib Site, Patch ID 1219 and Patch ID 1220    
at http://www.codeplex.com/unitycontributions/SourceControl/PatchList.aspx 

Patch ID 1219, Unity container is set up by using code in ASP.NET Global.cs
Patch ID 1220, Unity container is set up by using code in ASP.NET Global.cs and xml configuration.

This should help you to move on....

Regards,
Alexander
May 12, 2008 at 7:35 PM
Spring is a very mature project, and has a whole lot more in it than just a DI container. As such, that kind of rich integration doesn't exist for Unity, yet.

For what it's worth, the BuildUp method was added to Unity specifically for things like ASP.NET - where the framework creates the object before you can.

Jun 11, 2008 at 10:56 AM
I have made a little efforts to integrate aspx and unity, and I make a HttpHandlerFactory to inject dependency to webform pages, the code is listed below

public class UnityHttpHandlerFactory : IHttpHandlerFactory
{
    private static readonly IUnityContainer unityContainer;

    static UnityHttpHandlerFactory()
    {
        //初始化UnityContainer
        string containerName = ConfigurationManager.AppSettings["HttpHandlerUnityContainerName"];
        if (String.IsNullOrEmpty(containerName))
        {
            containerName = "HttpHandlerContainer";
        }

        unityContainer = new UnityContainer();
        UnityConfigurationSection section
            = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
        section.Containers[containerName].Configure(unityContainer);
    }

    protected UnityHttpHandlerFactory()
    {
    }

    /// <summary>
    /// 获取Unity窗口,通过重写此方法可以支持硬编码方式的Unity窗口配置.
    /// </summary>
    protected virtual IUnityContainer UnityContainer
    {
        get
        {
            return unityContainer;
        }
    }

    #region IHttpHandlerFactory Members

    public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
    {
        IHttpHandlerFactory pageFactory = CreatePageFactory();
        IHttpHandler page = pageFactory.GetHandler(context, requestType, url, pathTranslated);
        page = Build(page);
        return page;
    }

    public void ReleaseHandler(IHttpHandler handler)
    {
        IHttpHandlerFactory pageFactory = CreatePageFactory();
        pageFactory.ReleaseHandler(handler);
    }

    #endregion

    private static IHttpHandlerFactory CreatePageFactory()
    {
        IHttpHandlerFactory pageFactory =
            Activator.CreateInstance(typeof(PageHandlerFactory), true) as IHttpHandlerFactory;
        if (pageFactory == null)
        {
            throw new ApplicationException(
                "无法初始化PageHandlerFactory...");
        }
        return pageFactory;
    }

    private IHttpHandler Build(IHttpHandler page)
    {
        try
        {
            return UnityContainer.BuildUp(page.GetType().BaseType, page) as IHttpHandler;
        }
        catch (Exception)
        {
            return page;
        }
    }
}

To use it, you must apply the web.config a unity section, and the configuration is something like:
<unity>
  
<typeAliases>
    
<typeAlias alias="singleton" type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager, Microsoft.Practices.Unity"/>
  
</typeAliases>
  
<containers>
    
<container name="HttpHandlerContainer">
      
<types>
        
<!-- Default页面的依赖 -->
        
<type type="GDev.Test.WebApp.Default, GDev.Test.WebApp" mapTo="GDev.Test.WebApp.Default, GDev.Test.WebApp">
          
<lifetime type="singleton" />
          
<typeConfig extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration">
            
<property name="UserService" propertyType="GDev.Test.WebApp.IUser, GDev.Test.WebApp">
              
<dependency />
            
</property>
          
</typeConfig>
        
</type>
        
<type type="GDev.Test.WebApp.IUser, GDev.Test.WebApp" mapTo="GDev.Test.WebApp.MyUser, GDev.Test.WebApp">
          
<lifetime type="singleton" />
        
</type>
      
</types>
    
</container>
  
</containers>
</unity>

Lastly you should change the HttpHandlerFactory:
<remove verb="*" path="*.aspx"/>
<add verb="*" path="*.aspx" type="Cst.Core.Web.Factory.UnityHttpHandlerFactory, Cst.Core.Web"/>

Jun 19, 2008 at 10:28 AM
Why not to use HttpApplication.PreRequestHandlerExecute event. The code would be simplier.
Also the useful link Integrating ObjectBuilder with ASP.NET
Jun 20, 2008 at 8:03 AM
I've decided to implement the following variant:

  public class DependencyInjectionHttpModule : IHttpModule
  {
    private IUnityContainer container;

    private void ContextPreRequestHandlerExecute(object sender, EventArgs e)
    {
      Page page = HttpContext.Current.CurrentHandler as Page;
      if (page != null)
      {
        page.PreInit += Page_PreInit;
      }
    }

    private void BuildUp(object o)
    {
      container.BuildUp(o.GetType(), o);     
    }

    private void Page_PreInit(object sender, EventArgs e)
    {
      Page page = sender as Page;

      BuildUp(page);

      BuildUpMaster(page.Master);

      BuildUpControls(page.Controls);
    }

    private void BuildUpControls(ControlCollection controls)
    {
      foreach (Control c in controls)
      {
        if (c is UserControl)
          BuildUp(c);

        BuildUpControls(c.Controls);
      }
    }

    private void BuildUpMaster(MasterPage page)
    {
      if (page != null)
      {
        BuildUp(page);
        BuildUpMaster(page.Master);
      }
    }

    #region IHttpModule Members

    public void Init(HttpApplication context)
    {
      container = ((IContainerAccessor) context).Container;
      context.PreRequestHandlerExecute += ContextPreRequestHandlerExecute;
    }

    public void Dispose()
    {
    }

    #endregion
  }

It allows injection into pages (including nested masters) and user controls.