Unity与ASP.NET的集成(官方方法)

最近有用到Unity与微软企业库与ASP.NET的集成,这样就可以将微软企业库作为一套解决方案,来搭建ASP.NET的项目框架,在很大程度上解决了一些常见的需要,如日志记录,异常处理等等。

在网上搜索的时候,发现了一些解决方案,但是都不太满意,后来依稀记得Unity的动手实验里面有这么个内容。

贴在这里,给有这个需要的广大群众和我自己留个记号,呵呵。

 

Introduction

In this lab, you will practice using Unity with an ASP.NET application. Because the creation of ASP.NET objects is managed by the ASP.NET infrastructure, the Unity container cannot be used to create them. Instead, the container will be used to apply injection to existing objects using the BuildUp method. For information about the BuildUp methods, see Using BuildUp to Wire Up Objects Not Created by the Container.

To begin, open the StocksTicker.sln file located in the Labs\Lab05\begin\StocksTicker folder.

Reviewing the Application

The application is a simplified ASP.NET version of the stocks ticker application used throughout these labs. Just like with the Windows Forms version of the application, stock symbols can be subscribed to, and the latest updates on the stocks are displayed in a table, as illustrated in Figure 6.

image

Figure 6
Stocks Ticker application

Task 1: Integrating with ASP.NET

In this task, the application will be updated to use a single, application-wide container to perform injection on its Web forms before they process requests.

Adding References to the Required Assemblies

To add references to the required assemblies

  1. Add references to the Microsoft.Practices.Unity, Microsoft.Practices.Unity.Configuration and Microsoft.Practices.ObjectBuilder2 assemblies from the Unity bin folder.
  2. Add a reference to the .NET Framework's System.Configuration assembly.

Updating the Default Page to Use Property Injection

To update the default page to use property injection

  1. Open the Default.aspx.cs file. If it is not visible, expand the node for the Default.aspx file.
  2. Add a using directive for the Unity namespace.
    using Microsoft.Practices.Unity;
    
  3. Remove the initialization code from the Page_Load method, as shown in the following code.
    protected void Page_Load(object sender, EventArgs e)
    {
        this.stockQuoteService = new MoneyCentralStockQuoteService();
        if (!this.IsPostBack)
        {
            UpdateQuotes();
        } 
    }
    
  4. Add the Dependency attribute to the StockQuoteService, as shown in the following code.
    private IStockQuoteService stockQuoteService;
    [Dependency]
    public IStockQuoteService StockQuoteService
    {
        get { return stockQuoteService; }
        set { stockQuoteService = value; }
    }
    

    Note:

    Configuration files cannot be used in this case because the assembly name for the page class is not known in advance so assembly-qualified type names cannot be expressed.

Adding a Global.asax File to Manage the Container

The HttpApplication class is used to define common methods in an ASP.NET application, so the code to manage the Unity container will be added to a new Global.asax file. For information about HTTP application classes, see HttpApplication Class.

To add a Global.asax file to manage the container

  1. Add a Global.asax file. Right-click the StocksTicker project node, point to Add, and then click New Item. Select the Global Application Class template, and then click Add, as shown in Figure 7.

    image  

    Figure 7
    Adding a new application class

  2. Add using statements for the required namespaces:
    using Microsoft.Practices.Unity;
    using Microsoft.Practices.Unity.Configuration;
    using System.Web.Configuration;
    using System.Web.UI;
    
  3. Add a constant named AppContainerKey with "application container" as its value:
    public class Global : System.Web.HttpApplication
    {
        private const string AppContainerKey = "application container";
    
        protected void Application_Start(object sender, EventArgs e)
        {
    
        }
    
  4. Add an ApplicationContainer property to store a Unity container in the application state using the key defined earlier.
    private IUnityContainer ApplicationContainer
    {
        get
        {
            return (IUnityContainer)this.Application[AppContainerKey];
        }
        set
        {
            this.Application[AppContainerKey] = value;
        }
    }
    

    Note:

    The container is stored in the application's shared state.

  5. Add the following method to set up a container using settings from the configuration file.
    private static void ConfigureContainer(
        IUnityContainer container,
        string containerName)
    {
        UnityConfigurationSection section
            = WebConfigurationManager.GetWebApplicationSection("unity")
                as UnityConfigurationSection;
    
        if (section != null)
        {
            UnityContainerElement containerElement
                = section.Containers[containerName];
            if (containerElement != null)
            {
                containerElement.Configure(container);
            }
        }
    }
    
  6. Update the empty Application_Start method to create a Unity container, configure it with the information for the "application" container from the configuration file and set it as the value for the ApplicationContainer property.
    protected void Application_Start(object sender, EventArgs e)
    {
        IUnityContainer applicationContainer = new UnityContainer();
        ConfigureContainer(applicationContainer, "application");
    
        ApplicationContainer = applicationContainer;
    }
    
  7. Update the empty Application_End method to dispose the application's container.
    protected void Application_End(object sender, EventArgs e)
    {
        IUnityContainer applicationContainer = this.ApplicationContainer;
    
        if (applicationContainer != null)
        {
            applicationContainer.Dispose();
    
            this.ApplicationContainer = null;
        }
    }
    
  8. Add a method named Application_PreRequestHandlerExecute to intercept the ASP.NET execution pipeline and use the container to inject dependencies into the request handler if the handler is a Page.

    protected void Application_PreRequestHandlerExecute(object sender, EventArgs e)
    {
        Page handler = HttpContext.Current.Handler as Page;

        if (handler != null)
        {
            IUnityContainer container = ApplicationContainer;

            if (container != null)
            {
                container.BuildUp(handler.GetType(), handler);
            }
        }
    }

Adding Unity Configuration to the Web.config File

The configuration in a Web.config file uses the same schema as in an App.config file.

To add Unity configuration to the Web.config file

  1. Open the Web.config file.
  2. Add a declaration for the unity configuration section.
    <configSections>
      ...
      <section name="unity"
               type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
    </configSections>
    
  3. Add the unity section element.
      </system.diagnostics>
      <unity>
      </unity>
    </configuration>
    
  4. Add typeAlias elements for the types used throughout the labs.
    <unity>
      <typeAliases>
        <typeAlias
          alias="string"
          type="System.String, mscorlib" />
        <typeAlias
          alias="TraceSource"
          type="System.Diagnostics.TraceSource, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
    
        <typeAlias
          alias="singleton"
          type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager, Microsoft.Practices.Unity, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
    
        <typeAlias
          alias="ILogger"
          type="StocksTicker.Loggers.ILogger, StocksTicker" />
        <typeAlias
          alias="TraceSourceLogger"
          type="StocksTicker.Loggers.TraceSourceLogger, StocksTicker" />
    
        <typeAlias
          alias="IStockQuoteService"
          type="StocksTicker.StockQuoteServices.IStockQuoteService, StocksTicker" />
        <typeAlias
          alias="MoneyCentralStockQuoteService"
          type="StocksTicker.StockQuoteServices.MoneyCentralStockQuoteService, StocksTicker" />
      </typeAliases>
    </unity>
    
  5. Add elements for the containers collection and a container with the name application.
      </typeAliases>
    
      <containers>
        <container name=”application”>
        </container>
      </containers>
    </unity>
    
  6. Add the types element.
    <container name="application">
      <types>
      </types>
    </container>
    
  7. Add a type element to map the IStockQuoteService interface to the MoneyCentralStockQuoteService class with a property element to inject the Logger property and define a singleton lifetime manager.

    <container name="application">
      <types>
        <type type="IStockQuoteService" mapTo="MoneyCentralStockQuoteService">
          <lifetime type="singleton"/>
          <typeConfig>
            <property name="Logger" propertyType="ILogger"/>
          </typeConfig>
        </type>
      </types>
    </container>

  8. Add a type element to map the ILogger interface to the TraceSourceLogger class, defining a singleton lifetime manager and injecting the "default" string in its constructor. This mapping is required to inject the Logger property on the MoneyCentralStockQuoteService instance.
    <container name="application">
      <types>
        <type type="ILogger" mapTo="TraceSourceLogger">
          <lifetime type="singleton"/>
          <typeConfig>
            <constructor>
              <param name="sourceName" parameterType="string">
                <value value="default"/>
              </param>
            </constructor>
          </typeConfig>
        </type>
        <type type="IStockQuoteService" mapTo="MoneyCentralStockQuoteService">
          <typeConfig>
            <property name="Logger" propertyType="ILogger"/>
          </typeConfig>
        </type>
      </types>
    </container>
    

Running the Application

To run the application

  1. Launch the application. Open two browser instances, as shown in Figure 8, and open the application's URL in them. Use the application for a while in both browsers, subscribing to different sets of symbols.

     image

    Figure 8
    Multiple instances of the application

  2. Close the browsers and stop the development server. To do this, right-click the image icon in the taskbar, and then click Stop.
  3. Open the trace.log file located in the StocksTicker folder. The contents at the bottom of the file should look like the following log, with messages indicating the processing of the different sets of requests and the final two entries indicating that the service and the logger were disposed.
    default Information: 0 : Parsed result for YHOO GM 
        DateTime=2009-02-23T18:15:25.4761924Z
    default Information: 0 : Retrieving quotes for BAC MSFT 
        DateTime=2009-02-23T18:15:29.1101924Z
    default Information: 0 : Received result for BAC MSFT 
        DateTime=2009-02-23T18:15:29.5251924Z
    default Information: 0 : Parsed result for BAC MSFT 
        DateTime=2009-02-23T18:15:29.5251924Z
    default Information: 0 : Shutting down service
        DateTime=2009-02-23T18:15:44.6961924Z
    default Information: 0 : Shutting down logger
        DateTime=2009-02-23T18:15:44.6971924Z
    

Task 2: Using Per-Session Child Containers

In this task, a more sophisticated container management strategy will be implemented: the application-wide container will hold services shared by all sessions, but other objects will be managed by a session-specific container. In this case, the service used to retrieve quotes will not be shared, but its lifetime will be managed. Of course, this approach works only when session state is enabled and stored InProc.

Container hierarchies can be used to control the scope and lifetime of objects and to register different mappings in different context. In this task, a two-level hierarchy will be implemented. For information about container hierarchies, see Using Container Hierarchies.

Updating the Global.asax File to Manage Per-Session Containers

To update the Global.asax file to manage per-session containers

  1. Open the Global.asax file.
  2. Add a constant named SessionContainerKey with "session container" as its value:
    public class Global : System.Web.HttpApplication
    {
        private const string AppContainerKey = "application container";
        private const string SessionContainerKey = "session container";
    
  3. Add a SessionContainer property to store a Unity container in the application state using the key defined earlier.
    private IUnityContainer SessionContainer
    {
        get
        {
            return (IUnityContainer)this.Session[SessionContainerKey];
        }
        set
        {
            this.Session[SessionContainerKey] = value;
        }
    }
    
  4. Add a Session_Start method to create a child container of the application's container using the CreateChildContainer method, configure it with the information for the "session" container from the configuration file and set it as the value for the SessionContainer property.
    protected void Session_Start(object sender, EventArgs e)
    {
        IUnityContainer applicationContainer = this.ApplicationContainer;
    
        if (applicationContainer != null)
        {
            IUnityContainer sessionContainer 
                = applicationContainer.CreateChildContainer();
            ConfigureContainer(sessionContainer, "session");
    
            this.SessionContainer = sessionContainer;
        }
    }
    
  5. Add a Session_End method to dispose the session's container.
    protected void Session_End(object sender, EventArgs e)
    {
        IUnityContainer sessionContainer = this.SessionContainer;
        if (sessionContainer != null)
        {
            sessionContainer.Dispose();
    
            this.SessionContainer = null;
        }
    }
    
  6. Update the Application_PreRequestHandlerExecute method to use the session container to BuildUp the request's handler.
    protected void Application_PreRequestHandlerExecute(object sender, EventArgs e)
    {
        Page handler = HttpContext.Current.Handler as Page;
    
        if (handler != null)
        {
            IUnityContainer container = SessionContainer;
    
            if (container != null)
            {
                container.BuildUp(handler.GetType(), handler);
            }
        }
    }
    

Updating the Unity Configuration with a Session Container

To update the Unity configuration with a session container

  1. Open the Web.config file.
  2. Add a new container element with name session as a child of the containers element.
    <containers>
      <container name="application">
        ...
      </container>
    
      <container name="session">
        <types>
        </types>
      </container>
    </containers>
    
  3. Add a type element to map the IStockQuoteService interface to the MoneyCentralStockQuoteService class with a property element to inject the Logger property and define a singleton lifetime manager.
    <container name="session">
      <types>
        <type type="IStockQuoteService" mapTo="MoneyCentralStockQuoteService">
          <lifetime type="singleton"/>
          <typeConfig>
            <property name="Logger" propertyType="ILogger"/>
          </typeConfig>
        </type>
      </types>
    </container>
    
  4. Remove the type element mapping the IStockQuoteService interface from the types collection for the application container.
    <container name="application">
      <types>
        <type type="ILogger" mapTo="TraceSourceLogger">
          <lifetime type="singleton"/>
          <typeConfig>
            <constructor>
              <param name="sourceName" parameterType="string">
                <value value="default"/>
              </param>
            </constructor>
          </typeConfig>
        </type>
        <type type="IStockQuoteService" mapTo="MoneyCentralStockQuoteService">
          <typeConfig>
            <property name="Logger" propertyType="ILogger"/>
          </typeConfig>
        </type>
      </types>
    </container>
    

Running the Application

To run the application

  1. Launch the application. Open two browser instances and open the application's URL in them. Use the application for a while in both browsers, subscribing to different sets of symbols.
  2. Close one of the browser instances and wait for 90 seconds. The session timeout interval is set to one minute in the configuration file, so this wait should be enough for the session to expire.
  3. Close the other browser instance, and then stop the development Web server.
  4. Open the trace.log file located in the StocksTicker folder. The contents at the bottom of the file should look like the following log, with entries for each of the service instances and for the shared logger.
    default Information: 0 : Retrieving quotes for MSFT BAC 
        DateTime=2009-02-23T19:06:45.7471924Z
    default Information: 0 : Received result for MSFT BAC 
        DateTime=2009-02-23T19:06:46.1491924Z
    default Information: 0 : Parsed result for MSFT BAC 
        DateTime=2009-02-23T19:06:46.1491924Z
    default Information: 0 : Shutting down service
        DateTime=2009-02-23T19:07:00.0781924Z
    default Information: 0 : Retrieving quotes for MSFT BAC 
        DateTime=2009-02-23T19:07:05.7731924Z
    default Information: 0 : Received result for MSFT BAC 
        DateTime=2009-02-23T19:07:06.1841924Z
    default Information: 0 : Parsed result for MSFT BAC 
        DateTime=2009-02-23T19:07:06.1841924Z
    default Information: 0 : Retrieving quotes for MSFT BAC 
        DateTime=2009-02-23T19:07:25.7691924Z
    default Information: 0 : Received result for MSFT BAC 
        DateTime=2009-02-23T19:07:26.1791924Z
    default Information: 0 : Parsed result for MSFT BAC 
        DateTime=2009-02-23T19:07:26.1791924Z
    default Information: 0 : Shutting down service
        DateTime=2009-02-23T19:07:44.2521924Z
    default Information: 0 : Shutting down logger
        DateTime=2009-02-23T19:07:44.2541924Z
    

To verify you have completed the lab correctly, you can use the solution provided in the Labs\Lab05\end\StocksTicker folder.r.

Footer image

To give feedback, get assistance or download additional content please visit the Unity Application Block Community.

Copyright © 2009 by Microsoft Corporation. All rights reserved.

原文地址:https://www.cnblogs.com/HCOONa/p/1590856.html