您的位置:首页 > 其它

微软企业库5.0学习笔记(00)企业库主要内容

2010-06-08 15:54 459 查看
通常,你主要使用下列2种方法之一来创建企业库对象实例。
1.使用Unity服务器定位器(Using the Unity Service Locator):这是最简单的方法,如果你的应用只

有少量依赖,并且你不想使用现在的架构模式例如依赖注入,那么推荐使用这种方法。 它不需要初始化和设置。你只需配置你的应用使用企业库,然后调用服务定位器的方法来获取需要类型的企业库实例。
2.直接通过Unity容器。这个比较复杂的方法使你为你的层、组件、自定义类型通过现在架构模式例如依

赖注入获得全部的好处。它只需少量的配置,但需要在应用中保持对容器的引用。

你可以使用的其他方法:
1.如果你决定使用不同于Unity的容器,你可以使用其他服务定位器。
2.在之前的版本中使用传统的静态门面(static facades )和工厂
使用Unity服务器定位器:
创建企业库对象最简单的方法就是通过服务定位器创建需要的对象实例,而不是将他们注入到你的应用对像中。服务定位器实际上就是容器的包装,暴露一系列用来返回基于注册和映射的适当类型实例的方法。通过名称从数据访问模块获得实例

view plaincopy to clipboardprint?

C#

Database db = EnterpriseLibraryContainer.Current.GetInstance<Database>("mydatabase");

db.ExecuteNonQuery("DoSomethingInteresting");

Visual Basic

Dim db As Database = EnterpriseLibraryContainer.Current.GetInstance(Of Database)("mydatabase")

db.ExecuteNonQuery("DoSomethingInteresting")

C# Database db = EnterpriseLibraryContainer.Current.GetInstance<Database>("mydatabase");db.ExecuteNonQuery("DoSomethingInteresting"); Visual BasicDim db As Database =  EnterpriseLibraryContainer.Current.GetInstance(Of Database)("mydatabase") db.ExecuteNonQuery("DoSomethingInteresting")

直接访问Unity容器:
基本原则是代替获得你需要的对象,而是接收他们作为输入。一个容器,它基本上是一个用于存储类型注册和

映射和实例化请求类型的机制。当你的应用程序代码的请求(或解决)接口,一个基类,或通过定义一个依赖于该

类型的具体类型时,它被配置为返回一个适当类型的实例。
当使用依赖注入的时候你不需要明确请求实例;相反依赖注入机制决定需要的实例并注入它。依赖注入将你从

必须创建所有依赖对象并将他们传到指定目标中解脱出来。依赖注入容器为你创建对象,确定依赖关系。
如果你接受依赖注入的工作方式,或者你想通过容器来管理其周期,或者创建并修改类型注册和映射,你可以

专门创建一个容器并配置它。这意味着您可以解决您的应用程序中除了企业库对象之外的其他对象,例如用户界面

组件、试图模型、业务对象。
企业库提供EnterpriseLibraryCoreExtension 容器的扩展,可以很方便的用企业库配置信息来初始化和填充默

认的Unity容器。下例实例化一个新的Unity容器并添加扩展,使所有的企业库注册和映射都可用。

view plaincopy to clipboardprint?

C#

var container = new UnityContainer().AddNewExtension<EnterpriseLibraryCoreExtension>();

Visual Basic

Dim container = New UnityContainer().AddNewExtension(Of EnterpriseLibraryCoreExtension)();

C#var container = new UnityContainer().AddNewExtension<EnterpriseLibraryCoreExtension>(); Visual BasicDim container = New UnityContainer().AddNewExtension(Of EnterpriseLibraryCoreExtension)();


依赖注入示例:
通常,当您直接访问容器将受益于依赖注入,你将用它来解决自己的具体类,容器将注入企业库对象以及与所有其他对象和依赖.
下面的例子显示TaxCalculator类型具有两个依赖 ExceptionManager和LogWriter.

view plaincopy to clipboardprint?

C#

public class TaxCalculator

{

private ExceptionManager _exceptionManager;

private LogWriter _logWriter;

public TaxCalculator(ExceptionManager em, LogWriter lw)

{

this._exceptionManager = em;

this._logWriter = lw;

}

}

Visual Basic

Public Class TaxCalculator

Private _exceptionManager As ExceptionManager

Private _logWriter As LogWriter

Public Sub New(em As ExceptionManager, lw As LogWriter)

Me._exceptionManager = em

Me._logWriter = lw

End Sub

End Class

C# public class TaxCalculator {  private ExceptionManager _exceptionManager;  private LogWriter _logWriter;  public TaxCalculator(ExceptionManager em, LogWriter lw)   {    this._exceptionManager = em;    this._logWriter = lw;  }} Visual Basic  Public Class TaxCalculator  Private _exceptionManager As ExceptionManager  Private _logWriter As LogWriter  Public Sub New(em As ExceptionManager, lw As LogWriter)    Me._exceptionManager = em    Me._logWriter = lw  End SubEnd Class

当您有一个容器的引用,你可以用它来解决具体的对象,如TaxCalculator。

view plaincopy to clipboardprint?

C#

TaxCalculator calc = container.Resolve<TaxCalculator>();

Visual Basic

Dim calc As TaxCalculator = container.Resolve(Of TaxCalculator)()

C# TaxCalculator calc = container.Resolve<TaxCalculator>(); Visual Basic Dim calc As TaxCalculator = container.Resolve(Of TaxCalculator)()


容器会自动填充的解决实例中所有的依赖关系。如果TaxCalculator类被定义为另一种类型的依赖。当他的

父类被解析时,ExceptionManager和LogWriter将自动创建并注入。

非静态实例和实例工厂
所有的应用程序块包含非静态实例和非静态工厂取代5.0版本以前的静态方法和实例工厂.新的非静态实例和工厂类

不能直接实例化.



非晶态实例和工厂示例:
下面的示例使用GetInstance方法从异常处理应用模块获得ExceptionManager实例,并调用它的方法。

view plaincopy to clipboardprint?

C#

ExceptionManager em = EnterpriseLibraryContainer.Current.GetInstance<ExceptionManager>();

em.Process( () => MethodThatMightThrow(), "My Exception Policy");

Visual

Dim em As ExceptionManager = EnterpriseLibraryContainer.Current.GetInstance(Of ExceptionManager)();

em.Process(AddressOf MethodThatMightThrow, "My Exception Policy");

C# ExceptionManager em = EnterpriseLibraryContainer.Current.GetInstance<ExceptionManager>();em.Process( () => MethodThatMightThrow(), "My Exception Policy"); Visual Dim em As ExceptionManager =  EnterpriseLibraryContainer.Current.GetInstance(Of ExceptionManager)(); em.Process(AddressOf MethodThatMightThrow, "My Exception Policy");

下面的示例使用GetInstance方法从验证应用模块获得ValidatorFactory实例,并使用它创建一个对象来验证 Customer的成员。

view plaincopy to clipboardprint?

C#

ValidatorFactory factory = EnterpriseLibraryContainer.Current.GetInstance<ValidatorFactory>();

Validator<Customer> customerValidator = factory.CreateValidator<Customer>();

Customer myCustomer = new Customer("A name that is too long");

ValidationResults r = customerValidator.Validate(myCustomer);

if (!r.IsValid)

{

throw new InvalidOperationException("Validation error found.");

}

Visual Basic

Dim factory As ValidatorFactory = EnterpriseLibraryContainer.Current.GetInstance(Of

ValidatorFactory)()

Dim customerValidator As Validator(Of Customer)

= factory.CreateValidator(Of Customer)()

Dim myCustomer As New Customer("A name that is too long")

Dim r As ValidationResults = customerValidator.Validate(myCustomer)

If Not r.IsValid Then

Throw New InvalidOperationException("Validation error found.")

End If

C# ValidatorFactory factory = EnterpriseLibraryContainer.Current.GetInstance<ValidatorFactory>();Validator<Customer> customerValidator = factory.CreateValidator<Customer>();Customer myCustomer = new Customer("A name that is too long");ValidationResults r = customerValidator.Validate(myCustomer);if (!r.IsValid){  throw new InvalidOperationException("Validation error found.");} Visual BasicDim factory As ValidatorFactory = EnterpriseLibraryContainer.Current.GetInstance(Of ValidatorFactory)()Dim customerValidator As Validator(Of Customer) = factory.CreateValidator(Of Customer)()Dim myCustomer As New Customer("A name that is too long")Dim r As ValidationResults = customerValidator.Validate(myCustomer)If Not r.IsValid Then  Throw New InvalidOperationException("Validation error found.")End If


遗留的静态态外观( Facades )和工厂
为保持向前兼容
初始化并设置当前容器
EnterpriseLibraryContainer类默认包装一个Unity容器的实例,并通过Current属性和IServiceLocator接口的

实现暴露对它的引用。调用 GetInstance 方法是容器真正的工作。你可以通过配置专门设置一个Unity容器。配置是负责从一个特定的源获得配置信息,并应用到容器中作为一系列类型的注册和映射。下面的例子使用默认的Unity容器配置。

view plaincopy to clipboardprint?

C#

var container = new UnityContainer();

var configurator = new UnityContainerConfigurator(container);

// Read the configuration files and set up the container.

EnterpriseLibraryContainer.ConfigureContainer(configurator, ConfigurationSourceFactory.Create());

// The container is now ready to resolve Enterprise Library objects

Visual

Dim container = New UnityContainer()

Dim configurator = New UnityContainerConfigurator(container)

' Read the configuration files and set up the container.

EnterpriseLibraryContainer.ConfigureContainer(configurator, ConfigurationSourceFactory.Create())

' The container is now ready to resolve Enterprise Library objects

C# var container = new UnityContainer();var configurator = new UnityContainerConfigurator(container);// Read the configuration files and set up the container.EnterpriseLibraryContainer.ConfigureContainer(configurator, ConfigurationSourceFactory.Create());// The container is now ready to resolve Enterprise Library objects Visual  Dim container = New UnityContainer() Dim configurator = New UnityContainerConfigurator(container) ' Read the configuration files and set up the container.EnterpriseLibraryContainer.ConfigureContainer(configurator, ConfigurationSourceFactory.Create()) ' The container is now ready to resolve Enterprise Library objects

如果你没有在应用程序中是用依赖注入风格,或者如果您使用快捷方式来初始化和填充的容器,你通常不用关心实

现细节。但是有些场合你想改变底层容器,比如:
1。你有一个应用程序为一些事情而使用依赖注入容器,但是仍有就的企业库客户端代码在使用,你希望在不重写

对静态外观调用的情况下整合所有的东西。
2。你的应用程序使用静态外观或者 EnterpriseLibraryContainer.Current.GetInstance 获得企业库对象并且你

希望使用一个源而不是应用程序的配置文件来改变最终配置。
改变容器相当容易。你所需要的就是实现 IServiceLocator 接口。 不过,如果你想从配置源加载配置信息,

你会得益于使用IConfigurationSource实例和配置,以及IServiceLocator接口的实现。
一个实现了IConfigurationSource接口的对象包含企业库的配置信息。企业库附带的几个实现能够通过应用程

序配置文件、单独的文件、内存字典中读取这些信息。它将与配置一起来建立容器。
下面的代码演示如何使用UnityContainerConfigurator配置来建立容器、配置容器、使用ServiceLocator包装

容器。

view plaincopy to clipboardprint?

C#

IUnityContainer container = new UnityContainer();

UnityContainerConfigurator configurator = new UnityContainerConfigurator(container);

IConfigurationSource configSource = ReadConfigSource();

EnterpriseLibraryContainer.ConfigureContainer(configurator, configSource);

IServiceLocator locator = new UnityServiceLocator(container);

EnterpriseLibraryContainer.Current = locator;

Visual Basic

Dim container As IUnityContainer = New UnityContainer()

Dim configurator As UnityContainerConfigurator _

= New UnityContainerConfigurator(container)

Dim configSource As IConfigurationSource = ReadConfigSource()

EnterpriseLibraryContainer.ConfigureContainer(configurator, configSource)

Dim locator As IServiceLocator = New UnityServiceLocator(container)

EnterpriseLibraryContainer.Current = locator

C# IUnityContainer container = new UnityContainer();UnityContainerConfigurator configurator = new UnityContainerConfigurator(container);IConfigurationSource configSource = ReadConfigSource(); EnterpriseLibraryContainer.ConfigureContainer(configurator, configSource);IServiceLocator locator = new UnityServiceLocator(container);EnterpriseLibraryContainer.Current = locator; Visual BasicDim container As IUnityContainer = New UnityContainer()  Dim configurator As UnityContainerConfigurator _    = New UnityContainerConfigurator(container) Dim configSource As IConfigurationSource = ReadConfigSource()  EnterpriseLibraryContainer.ConfigureContainer(configurator, configSource) Dim locator As IServiceLocator = New UnityServiceLocator(container) EnterpriseLibraryContainer.Current = locator


如果您使用的是企业库的默认容器实现(Unity),您可以使用下面的代码实现相同的结果:

view plaincopy to clipboardprint?

C#

EnterpriseLibraryContainer.Current = EnterpriseLibraryContainer.CreateDefaultContainer(ReadConfigSource());

Visual Basic

EnterpriseLibraryContainer.Current = EnterpriseLibraryContainer.CreateDefaultContainer(ReadConfigSource());

通常,如果你不使用构造函数、属性或方法调用注入,以解决您的应用程序在初始化过程中的依赖,你将需要保留一个引用到容器,以便能够通过直接访问它来解决相应的对象。不过,也有些情况你可能希望在初始化后能够引用容器。下面是一些情况下,您可以考虑储存容器的引用,以便在您的代码中使用:

如果你使用ASP.NET Web 窗体或创建web服务。你必须能够解决每一页或每个服务请求的对象,如果每次都创建容器并加载企业库的配置信息或者你自己的注册信息就资源方面来说那是相当昂贵的。这种情况系通常需要把容器存储到Application字段或者你自己的服务实现中,以便在每个请求的时候使用它来解决实例。

如果你正在创建控制台应用或用户组件(而不是一个拥有用户接口或Web服务的应用程序)。

如果你使用Unity作为你的容器,你可以在你的启动代码中创建容器并加载企业库容器扩展,然后用Resolve方法来解决其他类需要的依赖. 定义在这些类中的任何依赖将自动填充。你可以在整个应用程序的生命拥有一个全局变量。请注意不建议销毁容器。

如果你想在容器中为自己的对象存储注册

您可以选择使用一个单独的容器,虽然你也可以很容易使用的拥有使用企业库配置注册的默认容器。

如果你希望能够解决需求的对象实例,而不是总是在类实例化的时候才解决。



如果一个类只在某些情况下需要,从容器中直接调用方法来解决实例将会更有用,而不是当类实例化的时候才通过构成函数、属性或方法调用注入来创建它们。下列表格将帮助你理解在基于保单或富客户端(例如使用winfows窗体、WPF、silverlight)中应该在什么时候在什么地方拥有容器的实例。



下列表格将帮助你理解在基于请求(例如使用ASP.NET、WEB服务)中应该在什么时候在什么地方拥有容器的实例。

应用启动时候的处理对象的图例



处理并注入需要的对象

如果你不选择在应用启动的时候加载所有的应用依赖,你可以使用容器处理你需要的任何企业库对象。你可以用它来处理你自己的任何类或这拥有公共构造函数并且在容器中有合适注册的其他对象。

下图显示你可以用容器生成需要的对想的几种方法的概述。



虽然他们是不同的技术,但是他们具有相同的基本特征。特别是他们都使用窗体对象来实现用户接口,并且都允许你指定应用程序启动时运行的代码。默认情况下,启动代码只是加载并显示主窗体,但是你可以修改它来创建一个统一的容器,用企业库信息组装它,并处理应用中使用的对象。例如,为了减少启动时间和使用内存,你可能不希望在启动是创建所有窗体。你可以存储一个容器的对象来处理窗体和其他需要的对象。

Windows窗体应用程序

下面显示怎么在windows窗体中创建并组装企业库容器

view plaincopy to clipboardprint?


WPF应用程序[/code]
Wpf应用程序使用启动代码加载并显示主窗体。

当创建一个WPF工程时, Visual Studio创建一个应用程序定义文件.使用C#的话, 它被命名App.xaml 并有一个关联的代码文件App.xaml.cs.

Xml文件内容

view plaincopy to clipboardprint?

<Application x:Class="Window1"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Startup="CreateContainer">

<Application.Resources>

</Application.Resources>

</Application>

<Application x:Class="Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Startup="CreateContainer"> <Application.Resources> </Application.Resources></Application>


Cs文件内容[/code]
view plaincopy to clipboardprint?

private void CreateContainer(object sender, StartupEventArgs e)

{

var container = new UnityContainer()

.AddNewExtension<EnterpriseLibraryCoreExtension>();

Window1 theWindow = container.Resolve<Window1>();

theWindow.Show();

}

private void CreateContainer(object sender, StartupEventArgs e){ var container = new UnityContainer() .AddNewExtension<EnterpriseLibraryCoreExtension>(); Window1 theWindow = container.Resolve<Window1>(); theWindow.Show();}

static void Main()

{

var container = new UnityContainer()

.AddNewExtension<EnterpriseLibraryCoreExtension>();

Application.Run(container.Resolve<Form1>());

}

static void Main(){ var container = new UnityContainer() .AddNewExtension<EnterpriseLibraryCoreExtension>(); Application.Run(container.Resolve<Form1>());}

在ASP.NET Web窗体应用程序中,推荐的方法是将容器存到由Application字典对象提供的全局状态。当需要的时候你可以访问容器,甚至使用HTTP模块自动完成对页面上控件的注入。

通常情况下,你应该使用Application字典对象来存储容器的单个实例。您可能决定创建主要容器的子容器,并将它们存储到每个用户的Session对象中,甚至是每个请求,在这些子容器中注册自定义类型和映射。但是,这可能降低应用的性能,通常应尽可能避免创建额外的容器。

ASP.NET应用程序实例化容器的技术方法及限制:

1基本方法。适合小项目

2依赖注入的推荐方法。能在运行时自动完成对页面控件的注入。

3.限制和替代途径。
基本方法

通过Global.asax文件的Application_Start事件来创建并构建容器。

view plaincopy to clipboardprint?

protected void Application_Start(object sender, EventArgs e)

{

Application.Lock();

try

{

var myContainer = Application["EntLibContainer"] as IUnityContainer;

if (myContainer == null)

{

myContainer = new UnityContainer();

myContainer.AddExtension(new EnterpriseLibraryCoreExtension());

// Add your own custom registrations and mappings here as required

Application["EntLibContainer"] = myContainer;

}

}

finally

{

Application.UnLock();

}

}

protected void Application_Start(object sender, EventArgs e){ Application.Lock(); try { var myContainer = Application["EntLibContainer"] as IUnityContainer; if (myContainer == null) { myContainer = new UnityContainer(); myContainer.AddExtension(new EnterpriseLibraryCoreExtension()); // Add your own custom registrations and mappings here as required Application["EntLibContainer"] = myContainer; } } finally { Application.UnLock(); }}

依赖注入的推荐方法

虽然上面提供的方法为你访问容器提供了一种途径,但是存在一些限制。这意味着你必须编写代码来处理您需要的类的实例,而且减少了代码的可发现性(discoverability)和可测性。如果你使用Unity容器,那么一个更好的方法就是通过容器的每个请求都使用BuildUp方法来构建依赖。这意味着你只需要关心你的空间和类的应用合适的属性,或着在容器中配置注入注册和映射。在运行时注入需要的企业库对象和你自己的类。

一种方法是创建HTTP模块当一个页面加载的时候自动为所有依赖创建注入。为了做到这一点,你需要一个HTTP模块在页面初始化执行过程中执行代码,以填充依赖。还可以使用Global.asax中的Application_Start方法的来创建和填充容器,类HttpApplicationState的一个扩展方法将容器暴露给应用程序代码.一旦创建了这些,只需要应用配置中的一行可使你应用中的控件和类能够自动依赖注入。

为自动依赖注入准备一个ASP.NET应用

1.在工程中创建一个新的ASP.NET HTTP模块类(例如命名UnityHttpModule)捕获PreRequestHandlerExecute事件并执行遍历当前页请求的完全控制树的代码,应用Unity BuildUp 方法到每个控件。

2.编辑应用程序的Web.config文件添加新的HTTP模块,并将它放到其他HTTP模块之前,这样它就可以最先执行。下面描述怎么添加上一步的HTTP模块

view plaincopy to clipboardprint?

<httpModules>

<add name="UnityModule" type="Unity.Web.UnityHttpModule, Unity.Web" />

... other HTTP modules defined here

</httpModules>

<httpModules> <add /> ... other HTTP modules defined here</httpModules>


3.创建一个类实现HttpApplicationState(提供一个访问容器的方法)的扩展方法,这个方法应该创建Unity容器并将它存储到Application字典中,如果存在则返回它的实例。[/code]
4.添加一个全局应用程序类文件(Global.asax中)到你的应用程序,并在Global.asax.cs中添加Application_Start事件处理代码。下面显示如何添加注册到特定的类型中,如IMyService, CustomerService, DataService


view plaincopy to clipboardprint?protected void Application_Start(object sender, EventArgs e)
{
IUnityContainer myContainer = Application.GetContainer();
myContainer.AddExtension(new EnterpriseLibraryCoreExtension());

myContainer.RegisterType<IMyService, CustomerService>();
myContainer.RegisterType<IMyService, DataService>("CustomerData",
new ContainerControlledLifetimeManager());
myContainer.RegisterInstance("myArray", new string[] {"Item 1", "Item 2" });
}
protected void Application_Start(object sender, EventArgs e){  IUnityContainer myContainer = Application.GetContainer();  myContainer.AddExtension(new EnterpriseLibraryCoreExtension());   myContainer.RegisterType<IMyService, CustomerService>();  myContainer.RegisterType<IMyService, DataService>("CustomerData",                           new ContainerControlledLifetimeManager());  myContainer.RegisterInstance("myArray", new string[] {"Item 1", "Item 2" });}

限制及替代方法

上述建议的技术不会自动执行构造注入到页面中的控件和类。它使用容器的BuildUp 方法,因为ASP.NET已经创建了控制和类的实例。这意味着自动构造注入不会发生。相反,你可以使用属性(setter)注入,或为类型创建控件和类的方法并定义参数加以解决,然后定义为使用属性或容器注册的InjectionMethod。这就构造了延迟构造。整个容器中Unity将决定参数的类型并调用方法。当然也可以存储一个实例在你的代码中处理对象。

您可以使用HTTP模块,一个到ASP.NET HttpApplicationState类的扩展,在Global.asax编写代码强制ASP.NET在每一个页面请求时自动注入依赖的对象,就像在ASP.NET Web窗体应用程序中讨论的一样.

下列方法显示了一个合适的方法能够获取PreRequestHandlerExecute事件将它自己注入到ASP.NET的执行流水线,在每个页面请求中通过容器的BuildUp方法运行Http模块,并获取OnPageInitComplete事件。当OnPageInitComplete执行时模块代码按照所有的控件树运行,并通过容器的BuildUp方法处理每个控件。

BuildUp方法获取已经存在的对象实例,处理并填充类的依赖,返回实例。如果没有依赖则返回最初的实例

view plaincopy to clipboardprint?using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using Microsoft.Practices.Unity;

namespace Unity.Web
{
public class UnityHttpModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.PreRequestHandlerExecute += OnPreRequestHandlerExecute;
}

public void Dispose() { }

private void OnPreRequestHandlerExecute(object sender, EventArgs e)
{
IHttpHandler currentHandler = HttpContext.Current.Handler;
HttpContext.Current.Application.GetContainer().BuildUp(
currentHandler.GetType(), currentHandler);

// User Controls are ready to be built up after page initialization is complete
var currentPage = HttpContext.Current.Handler as Page;
if (currentPage != null)
{
currentPage.InitComplete += OnPageInitComplete;
}
}

// Build up each control in the page's control tree
private void OnPageInitComplete(object sender, EventArgs e)
{
var currentPage = (Page)sender;
IUnityContainer container = HttpContext.Current.Application.GetContainer();
foreach (Control c in GetControlTree(currentPage))
{
container.BuildUp(c.GetType(), c);
}
context.PreRequestHandlerExecute -= OnPreRequestHandlerExecute;
}

// Get the controls in the page's control tree excluding the page itself
private IEnumerable<Control> GetControlTree(Control root)
{
foreach (Control child in root.Controls)
{
yield return child;
foreach (Control c in GetControlTree(child))
{
yield return c;
}
}
}
}
}
using System;using System.Collections.Generic;using System.Web;using System.Web.UI;using Microsoft.Practices.Unity;namespace Unity.Web{  public class UnityHttpModule : IHttpModule  {    public void Init(HttpApplication context)    {      context.PreRequestHandlerExecute += OnPreRequestHandlerExecute;    }    public void Dispose() { }    private void OnPreRequestHandlerExecute(object sender, EventArgs e)    {      IHttpHandler currentHandler = HttpContext.Current.Handler;      HttpContext.Current.Application.GetContainer().BuildUp(                          currentHandler.GetType(), currentHandler);      // User Controls are ready to be built up after page initialization is complete      var currentPage = HttpContext.Current.Handler as Page;      if (currentPage != null)      {        currentPage.InitComplete += OnPageInitComplete;      }    }    // Build up each control in the page's control tree    private void OnPageInitComplete(object sender, EventArgs e)    {      var currentPage = (Page)sender;      IUnityContainer container = HttpContext.Current.Application.GetContainer();      foreach (Control c in GetControlTree(currentPage))      {        container.BuildUp(c.GetType(), c);      }      context.PreRequestHandlerExecute -= OnPreRequestHandlerExecute;    }    // Get the controls in the page's control tree excluding the page itself    private IEnumerable<Control> GetControlTree(Control root)    {      foreach (Control child in root.Controls)      {        yield return child;        foreach (Control c in GetControlTree(child))        {          yield return c;        }      }    }  }}

下面显示了一个应用程序状态的实现,并暴露一个静态的 GetContainer方法,这个方法能够在

Application状态中创建一个新的统一容器,如果不存在的话,或者返回一个存在的实例的引用。

view plaincopy to clipboardprint?

using System.Web;
using Microsoft.Practices.Unity;

namespace Unity.Web
{
public static class HttpApplicationStateExtensions
{
private const string GlobalContainerKey = "EntLibContainer";

public static IUnityContainer GetContainer(this HttpApplicationState appState)
{
appState.Lock();
try
{
var myContainer = appState[GlobalContainerKey] as IUnityContainer;
if (myContainer == null)
{
myContainer = new UnityContainer();
appState[GlobalContainerKey] = myContainer;
}
return myContainer;
}
finally
{
appState.UnLock();
}
}
}
}
using System.Web;using Microsoft.Practices.Unity;namespace Unity.Web{  public static class HttpApplicationStateExtensions  {    private const string GlobalContainerKey = "EntLibContainer";    public static IUnityContainer GetContainer(this HttpApplicationState appState)    {      appState.Lock();      try      {        var myContainer = appState[GlobalContainerKey] as IUnityContainer;        if (myContainer == null)        {          myContainer = new UnityContainer();          appState[GlobalContainerKey] = myContainer;        }        return myContainer;      }      finally      {          appState.UnLock();      }    }  }}

在Web服务应用程序要初始化的容器和填充其依赖,需要来自应用程序类型的不同方法暴露用户接口(例如Windows Forms, WPF, and ASP.NET Web Forms)。本主题描述了ASP.NET的Web服务(ASMX)可能的解决方案和资源,帮助您实现在WCF应用程序。     ASP.NET Web服务应用程序

ASP.NET Web服务应用程序可以部分的使用主题ASP.NET Web窗体应用程序中的方法。您可以添加类HttpApplicationState的扩展方法的创建和公开容器,代码添加到应用程序的Global.asax文件中添加代码将企业库扩展加到容器中。不过,由于有在ASMX应用中没有没有UI控件,您不能像ASP.NET Web窗体应用程序描述那样使用HTTP模块。

不过,你可以调用HttpContext.Current.Application.GetContainer()扩展方法访问容器。 你可以容器的引用通过当前类的BuildUp方法填充你通过属性定义的依赖例如,下面的代码使用依赖注入,解决实现了ImyService接口的类的实例,并使用它来计算UseDataService方法返回的值。

view plaincopy to clipboardprint?

using System.Web;

public class MyWebService : System.Web.Services.WebService
{
private IMyService theService;

public MyWebService()
{
// Pass this class through the container using the BuildUp method
HttpContext.Current.Application.GetContainer().BuildUp(this);
}

[Dependency]
public IMyService DataService
{
get { return theService; }
set { theService = value; }
}

[WebMethod]
public string UseDataService()
{
return "The value you require is " + theService.DoSomething();
}
}
using System.Web;public class MyWebService : System.Web.Services.WebService{  private IMyService theService;  public MyWebService()  {    // Pass this class through the container using the BuildUp method        HttpContext.Current.Application.GetContainer().BuildUp(this);  }  [Dependency]  public IMyService DataService  {    get { return theService; }    set { theService = value; }  }  [WebMethod]  public string UseDataService()  {    return "The value you require is " + theService.DoSomething();  }}

作为选择,你可以使用ASP.NET Web窗体应用程序中的展示的基本方法,创建并组装在Application字典对象中的容器,然后再需要的时候通过你的web方法来访问它

    WCF应用程序

在WCF中你可以使用与此主题中描述的基本方针类似的技术。然而,在WCF中没有存储的HttpApplication状态。代替的方法,你可以使用具有InstanceContextMode InstanceContext ,它被设为单例,并适用于所有的请求。你必须通过实现Iextension接口创建的InstanceContext的自定义扩展
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: