gpt4 book ai didi

c# - ASP.NET WebForms 使用 IoC 动态加载 WebUserControls

转载 作者:行者123 更新时间:2023-11-30 16:59:09 25 4
gpt4 key购买 nike

我正在尝试使用 IoC 加载网络用户控件。我正在使用 unity,我按照书中的示例进行设置。到目前为止一切顺利,但是当我注入(inject)看起来像各个控件本身的界面时,我遇到了问题。我正在尝试使用 LoadControl(type, arguments) 但未加载 Web 用户控件。

我环顾网络,找不到任何可以帮助我使用 IoC 动态加载网络用户控件的东西。

你们有其他加载策略吗?您需要有关我的尝试的更多信息吗?

问候

最佳答案

让您的 DI 容器连接您的 Page、HttpHandler 和 UserControls 对于 Web Forms 是绝对可能的,但是没有任何内置的东西,所以您必须自己做。有两种方法可以做到这一点。创建自定义 PageHandlerFactory 或创建自定义 HttpModule。由于 Hook PageHandlerFactory 的唯一方法是通过 web.config,因此我更喜欢使用 HttpModule。使用 HttpModule 时,您可以使用 System.Web.PreApplicationStartMethodAttribute(System.Web 程序集)和 Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility 注册它(Microsoft.Web.Infrastructure 程序集)。看起来像这样:

[assembly: System.Web.PreApplicationStartMethod(typeof(ModuleInitializer), "Init")]

public static class ModuleInitializer
{
public static void Init()
{
DynamicModuleUtility.RegisterModule(
typeof(WebFormsDependencyInjectionHttpModule));
}
}

自定义 HttpModule 的技巧是挂接到应用程序的 PreRequestHandlerExecute 事件。这允许您遍历页面层次结构并在页面执行之前注入(inject)任何依赖项。

public class WebFormsDependencyInjectionHttpModule : IHttpModule {
public static UnityContainer Container;
private HttpApplication application;

public void Init(HttpApplication context) {
this.application = context;
context.PreRequestHandlerExecute += this.PreRequestHandlerExecute;
}

public void Dispose() { }

internal static void InitializeInstance(object instance) {
Container.BuildUp(instance);
}

private void PreRequestHandlerExecute(object sender, EventArgs e) {
if (Container == null)
throw new InvalidOperationException("Set Container first.");

var handler = this.application.Context.CurrentHandler;
if (handler != null) {
InitializeHttpHandler(handler);
}
}

private void InitializeHttpHandler(IHttpHandler handler) {
InitializeInstance(handler);
if (handler is Page) {
PageInitializer.HookEventsForUserControlInitialization((Page)handler);
}
}
private sealed class PageInitializer { ... }
}

此模块只是确保在页面生命周期中尽早调用 Unity 的 BuildUp 方法来构建 PageIHttpHandler 实例。这允许您将依赖项注入(inject)您的 Page 类,但不会在任何使用的 UserControl 实例中注入(inject)任何依赖项。为此,该模块调用特殊的 PageInitializer.HookEventsForUserControlInitialization 方法。这里的 PageInitializer 类是:

internal sealed class PageInitializer {
private HashSet<Control> alreadyInitializedControls = new HashSet<Control>();
private Page page;

internal PageInitializer(Page page) {
this.page = page;
}

internal static void HookEventsForUserControlInitialization(Page page) {
var initializer = new PageInitializer(page);
page.PreInit += initializer.PreInit;
page.PreLoad += initializer.PreLoad;
}

private void PreInit(object sender, EventArgs e) {
this.RecursivelyInitializeMasterPages();
}

private void RecursivelyInitializeMasterPages() {
foreach (var masterPage in this.GetMasterPages())
this.InitializeUserControl(masterPage);
}

private IEnumerable<MasterPage> GetMasterPages() {
MasterPage master = this.page.Master;

while (master != null) {
yield return master;
master = master.Master;
}
}

private void PreLoad(object sender, EventArgs e) {
this.InitializeControlHierarchy(this.page);
}

private void InitializeControlHierarchy(Control control) {
var dataBoundControl = control as DataBoundControl;

if (dataBoundControl != null) {
dataBoundControl.DataBound += this.InitializeDataBoundControl;
} else {
var userControl = control as UserControl;

if (userControl != null)
this.InitializeUserControl(userControl);

foreach (var childControl in control.Controls.Cast<Control>()) {
this.InitializeControlHierarchy(childControl);
}
}
}

private void InitializeDataBoundControl(object sender, EventArgs e) {
var control = (DataBoundControl)sender;
if (control != null) {
control.DataBound -= this.InitializeDataBoundControl;
this.InitializeControlHierarchy(control);
}
}

private void InitializeUserControl(UserControl instance)
{
if (!this.alreadyInitializedControls.Contains(instance)) {
WebFormsDependencyInjectionHttpModule.InitializeInstance(instance);
// Ensure every user control is only initialized once.
this.alreadyInitializedControls.Add(instance);
}
}
}

PageInitializer 类将使该过程更进一步,并将 Hook 到页面的 PreInitPreLoad 事件以允许注入(inject)依赖项进入母版页并通过完整的控件层次结构将依赖项注入(inject)任何 UserControl。它甚至 Hook 到控件层次结构中任何 DataBoundControlDataBound 事件,以确保由 加载的任何 UserControl DataBoundControl 被初始化。

我认为这应该可以解决问题:-)

关于c# - ASP.NET WebForms 使用 IoC 动态加载 WebUserControls,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24209905/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com