在WebForms中使用Ninject注入Web用户控件

3

我有一个aspx页面,希望向其中注入对用户控件的引用。用户控件存储在单独的程序集中,并在运行时加载。注入用户控件后,应将其加载到页面的控件集合中。

一切似乎都正常工作,除了将控件添加到页面的部分。没有错误,但是控件的UI不显示。

global.asax.cs

protected override Ninject.IKernel CreateKernel()
{
    var modules = new INinjectModule[] { new MyDefaultModule() };
    var kernel = new StandardKernel(modules);

    // Loads the module from an assembly in the Bin
    kernel.Load("ExternalAssembly.dll");
    return kernel;
}

以下是另一个程序集中外部模块的定义:

public class ExternalModule : NinjectModule
{
    public ExternalModule() { }
    public override void Load()
    {
        Bind<IView>().To<controls_MyCustomUserControlView>();
    }
}

调试器显示,在应用程序运行时,会调用外部模块的加载函数,并将依赖项注入到页面中。

public partial class admin_MainPage : PageBase
{
    [Inject]
    public IView Views { get; set; }

在尝试将视图(这里是用户控件)添加到页面时,什么也没有显示出来。这是否与Ninject创建用户控件的方式有关?加载的控件似乎具有空的控件集合。

在aspx页面内

var c = (UserControl)Views;

// this won't show anything. even the Control collection of the loaded control (c.Controls) is empty
var view = MultiView1.GetActiveView().Controls.Add(c);

// but this works fine
MultiView1.GetActiveView().Controls.Add(new Label() { Text = "Nice view you got here..." });  

最后是视图/用户控制:
public partial class controls_MyCustomUserControlView : UserControl, IView
{
}

它只包含一个标签:

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="MyCustomUserControlView.ascx.cs" Inherits="controls_MyCustomUserControlView" %>

<asp:Label Text="Wow, what a view!" runat="server" />

在任何人建议MEF或System.Addin之前,我已经尝试过它们了。 - yanta
1个回答

2

通过使用用户控件作为资源来调用Page.LoadControl,可以使其正常工作。

然而,Page.LoadControl(typeof(controls_controls_MyCustomUserControlView), null)不起作用,但是Page.LoadControl("controls_MyCustomUserControlView.ascx")可以。

由于控件位于外部程序集中,因此首先需要创建一个VirtualPathProvider和VirtualFile,如http://www.codeproject.com/KB/aspnet/ASP2UserControlLibrary.aspx所述。

自定义VirtualPathProvider将用于检查用户控件是否位于外部程序集中,并且VirtualFile(用户控件)将从程序集中作为资源返回。

接下来设置Ninject模块以加载用户控件:

    public override void Load()
    {
        //Bind<IView>().To<controls_MyCustomUserControlView>();
        Bind<IView>().ToMethod(LoadControl).InRequestScope();
    }

    protected IView LoadControl(Ninject.Activation.IContext context)
    {
        var page = HttpContext.Current.Handler as System.Web.UI.Page;
        if (page != null)
        {
            //var control = page.LoadControl(typeof(controls_MyCustomUserControlView), null);
            var control = page.LoadControl("~/Plugins/ExternalAssembly.dll/MyCustomUserControlView.ascx");
            return (IView)control;
        }
        return null;
    }

"插件"只是一个前缀,用于在VirtualPathProvider中确定控件是否位于另一个程序集中。
如果您的用户控件有命名空间,请确保在LoadControl中为控件名称添加前缀。另外一件事是确保使用CodeBehind而不是CodeFile,因为ASP.NET将尝试加载CodeBehind文件。
<%@ Control Language="C#" AutoEventWireup="true" 
CodeBehind="~/MyCustomUserControlView.ascx.cs" Inherits="controls_MyCustomUserControlView" %>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接