我一直在按照“Microsoft Enterprise Library 5.0”文档中的步骤创建一个 HTTP 模块,以将对 Enterprise Library 容器的引用注入(inject)到 ASP.NET Web 应用程序的页面中。
它包含以下代码(也出现在网上 here ):
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;
}
}
}
}
}
此代码及其附带的说明存在许多问题。
1) 说明没有提到将此代码放在哪里。由于是一个类,所以我把它放在了我的ASP.NET网站项目的App_Code文件夹中。
事实上,这里是这段代码的说明:
Create a new ASP.NET HTTP module class (named, for example, UnityHttpModule ) in your project that captures the PreRequestHandlerExecute event and executes code that walks the complete control tree of the current page request, applying the Unity BuildUp method to each control.
2) HttpContext.Current.Application.GetContainer() 方法对我来说不存在,即使我使用了相同的 DLL 引用(我正在编码在 .NET 4.0 中)。
3) OnPageInitComplete 事件引用了一个“上下文”变量...在此上下文中似乎不存在。
关于我在这里缺少什么的任何想法?
最佳答案
似乎文档组织不当。
针对(2),没有解释的是HttpContext.Current.Application.GetContainer()方法实际上是一个扩展方法,它的实现就像所示的代码here
.
要使用此扩展方法,您只需导入“Unity.Web”命名空间即可。
这是扩展方法的副本:
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();
}
}
}
}
关于依赖注入(inject)模块代码,其实我只是用了basic method用于获取容器的实例,就我而言,它也同样有效。文档说依赖注入(inject) HTTP 模块代码提高了“可测试性”和“可发现性”,这有点含糊。
无论如何,这是基本方法的代码:
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();
}
}
因此,有了扩展代码,并在我的 global.asax 文件中编写了创建企业库容器实例的代码,剩下要做的唯一一件事就是编写代码以根据需要获取容器实例。所以当我想获取 LogWriter 类的实例时,我会这样写:
using Unity.Web;
public LogWriter getLogWriter()
{
var container = HttpContext.Current.Application.GetContainer();
return container.Resolve<LogWriter>();
}
需要 Unity.Web 命名空间来允许我们调用 GetContainer() 扩展方法。
关于c# - ASP.NET 依赖注入(inject) HTTP 模块(MS 企业库),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20632019/