最近有用到Unity与微软企业库与ASP.NET的集成,这样就可以将微软企业库作为一套解决方案,来搭建ASP.NET的项目框架,在很大程度上解决了一些常见的需要,如日志记录,异常处理等等。
在网上搜索的时候,发现了一些解决方案,但是都不太满意,后来依稀记得Unity的动手实验里面有这么个内容。
贴在这里,给有这个需要的广大群众和我自己留个记号,呵呵。
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.
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.
Figure 6
Stocks Ticker application
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.
To add references to the required assemblies
To update the default page to use property injection
using Microsoft.Practices.Unity;
protected void Page_Load(object sender, EventArgs e) {this.stockQuoteService = new MoneyCentralStockQuoteService();if (!this.IsPostBack) { UpdateQuotes(); } }
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.
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
Figure 7
Adding a new application class
using Microsoft.Practices.Unity; using Microsoft.Practices.Unity.Configuration; using System.Web.Configuration; using System.Web.UI;
public class Global : System.Web.HttpApplication { private const string AppContainerKey = "application container"; protected void Application_Start(object sender, EventArgs e) { }
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.
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); } } }
protected void Application_Start(object sender, EventArgs e) { IUnityContainer applicationContainer = new UnityContainer(); ConfigureContainer(applicationContainer, "application"); ApplicationContainer = applicationContainer; }
protected void Application_End(object sender, EventArgs e) { IUnityContainer applicationContainer = this.ApplicationContainer; if (applicationContainer != null) { applicationContainer.Dispose(); this.ApplicationContainer = null; } }
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);
}
}
}
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
<configSections> ... <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/> </configSections>
</system.diagnostics> <unity> </unity> </configuration>
<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>
</typeAliases> <containers> <container name=”application”> </container> </containers> </unity>
<container name="application"> <types> </types> </container>
<container name="application">
<types>
<type type="IStockQuoteService" mapTo="MoneyCentralStockQuoteService">
<lifetime type="singleton"/>
<typeConfig>
<property name="Logger" propertyType="ILogger"/>
</typeConfig>
</type>
</types>
</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>
To run the application
Figure 8
Multiple instances of the application
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
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.
To update the Global.asax file to manage per-session containers
public class Global : System.Web.HttpApplication { private const string AppContainerKey = "application container"; private const string SessionContainerKey = "session container";
private IUnityContainer SessionContainer { get { return (IUnityContainer)this.Session[SessionContainerKey]; } set { this.Session[SessionContainerKey] = value; } }
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; } }
protected void Session_End(object sender, EventArgs e) { IUnityContainer sessionContainer = this.SessionContainer; if (sessionContainer != null) { sessionContainer.Dispose(); this.SessionContainer = null; } }
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); } } }
To update the Unity configuration with a session container
<containers> <container name="application"> ... </container> <container name="session"> <types> </types> </container> </containers>
<container name="session"> <types> <type type="IStockQuoteService" mapTo="MoneyCentralStockQuoteService"> <lifetime type="singleton"/> <typeConfig> <property name="Logger" propertyType="ILogger"/> </typeConfig> </type> </types> </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>
To run the application
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.
To give feedback, get assistance or download additional content please visit the Unity Application Block Community.
Copyright © 2009 by Microsoft Corporation. All rights reserved.