繁体   English   中英

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

[英]ASP.NET WebForms dynamic load WebUserControls using IoC

我正在尝试使用IoC加载Web用户控件。 我正在使用统一,我按照书中的例子设置。 到目前为止一切都那么好,但是当我注入看起来单独控件本身的界面时,我遇到了问题。 我正在尝试使用LoadControl(类型,参数),但未加载Web用户控件。

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

你们中的任何人都有其他加载策略吗? 您是否需要有关我的尝试的更多信息?

问候

让你的DI容器连接你的Page,HttpHandler和UserControls绝对可以使用Web Forms,但是没有内置任何东西,所以你必须自己做。 有两种方法可以做到这一点。 您可以创建自定义PageHandlerFactory也可以创建自定义HttpModule 由于挂钩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事件。 这允许您在页面执行之前浏览页面层次结构并注入任何依赖项。

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实例。 这允许您将依赖项注入到Page类中,但不会在任何使用过的UserControl实例中注入任何依赖项。 要启用此功能,模块将调用特殊的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类将采取工艺更进了一步,将钩挂在页面的PreInitPreLoad的事件,让依赖注入到母版页和经过完全控制层次结构,以依赖注入任何UserControl 它甚至挂钩到控件层次结构中任何DataBoundControlDataBound事件,以确保DataBoundControl加载的任何UserControl都被初始化。

我认为这应该做的伎俩:-)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM