簡體   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