【问题标题】:Dependency injection: injecting user control in aspx page依赖注入:在aspx页面中注入用户控件
【发布时间】:2009-11-20 18:27:12
【问题描述】:

我需要构建一个“可定制的”asp.net web 应用程序(不是 asp.net mvc)。

我正在考虑使用 IoC 容器将用户控件注入到 aspx 页面中。

有人试过吗?

简而言之,我认为这是可以实现的:

  • 我使用 Scott Guthrie 的方法来构建可重用的“用户控件库”(请参阅​​他的文章“创建和使用用户控件库”)。

  • 该库中的控件和页面应具有动态接收用户控件的位置(例如,在 asp PlaceHolder 中)。

  • 在基于该库构建的自定义 Web 应用程序中,我创建了特定的用户控件。

  • 我以某种方式将它们放入 IoC 容器中,以便可以将它们注入到“用户控件库”的控件/页面中(例如,在 PlaceHolders 中)。

就是这样。

这基本上可以用 Spring.Net 来完成,正如这里所讨论的 http://blogger.forgottenskies.com/?p=70 但注入用户控件。

有人对这些东西有一些经验吗?还是听起来很傻?替代品?

我们的想法是有可能在我的“用户控件库”之上构建不同的 Web 应用程序,而无需触及该库。

例如:在我的库中,我有一个包含 4 个文本框的页面,对于一个特定的应用程序,我需要添加一个文本框,而无需更改页面的代码。这个想法是在该页面中放置一个占位符,并在该占位符中动态注入我的自定义文本框。

【问题讨论】:

    标签: asp.net dependency-injection


    【解决方案1】:

    这与您的情况并不完全相同,但我需要根据正在编辑的实体的运行时类型动态注入编辑器控件。我的所有控件都继承自这样的通用接口:

    public interface IEditor
    {
        bool CanHandle(EntityBase entity);
        void Display(EntityBase entity);
        void Save(EntityBase entity);
    }
    
    public partial class AddressEditor : UserControl, IEditor
    {
        public bool CanHandle(EntityBase entity)
        { 
            return (entity is Address);
        }
    
        public void Display(EntityBase entity)
        {
            var address = (Address)entity;
            addressLine1Textbox.Text = address.Line1;
            // etc...
        }
    
        public void Save(EntityBase entity)
        {
            var address = (Address)entity;
            address.Line1 = addressLine1Textbox.Text;
            // etc...
        }
    }
    

    然后使用 IoC 容器(在这种情况下为结构图)我可以通过类似的方式获得正确的用户控件

    var editorControl = ObjectFactory.GetAllInstancesOf<IEditor>().First(x => x.CanHandle(myEntity));
    

    这就是它变得棘手的地方,如果您像这样创建它的实例,则不能将用户控件添加到页面。您需要知道它的 .ascx 文件的位置。您可以通过编辑器界面公开它,以便每个控件都返回它:

    public string AscxFile { get { return "~/UserControls/AddressEditor.ascx"; } } // Implements IEditor.AscxFile
    

    然后在调用页面,使用LoadControl:

    var actualControl = LoadControl(editorControl.AscxFile);
    editorPlaceholder.Controls.Add(actualControl);
    editorControl.Display(myEntity);
    

    我更喜欢使用复合控件,它们需要更多的精力来创建,但无需担心 .ascx 文件,我可以直接将其添加到页面中:

    var editorControl = ObjectFactory.GetAllInstancesOf<IEditor>().First(x => x.CanHandle(myEntity));
    editorPlaceholder.Controls.Add((Control)editorControl);
    editorControl.Display(myEntity);
    

    确保您在 Page.OnInit 阶段添加控件,以便它可以参与 ViewState,并且在回发之间不会被记住,因此您必须每次都这样做。

    最后一步是使用您选择的 IoC 工具进行连接,我使用 StructureMap 自动加载 IEditor 的所有实例,但我可以在应用程序代码或 xml 配置中的任何位置进行更改。

    【讨论】:

      【解决方案2】:

      我们使用类似的模型构建了一套应用程序。
      我们有一个所谓的 PageBuilder,它通过注入 UserControls 和 WebParts 来构造每个页面。

      一切都是可配置的(页面布局、页面控件、控件位置等),因此无需更改页面、用户控件或 WebPart 中的任何代码。 (除非需要添加/更改某些功能)。

      我们甚至在控件中进行配置和设置,以根据 SQL 查询、模式、当前页面等各种因素来改变行为。

      基本上是这样工作的:

      • 为当前页面创建布局表。
      • 获取要显示的 UserControl 和 WebPart。
      • 将每个 UserControl 和 WebPart 放在正确的位置。
      • 将设置应用到每个 UserControl 和 WebPart。

      所有 WebPart 都可以通过自定义发布者/订阅者事件模型相互通信。 IE。在 WebPart A 中,更改了下拉选择 => WebPart B 显示所选项目的数据。

      此模型允许我们构建高度可配置的应用程序,客户可以在其中设计布局和行为,而无需我们参与。

      您的模型似乎是我们模型的一个子集,我只能说它很容易使用。从开发人员和客户的角度来看。

      编辑:
      基本上,我们的框架由几个母版页和调用 PageBuilder 的基本页组成。
      每个母版页用于不同类型的对象:页面、用户控件、WebPart、灯箱等。
      每个 aspx 页面都包含一个用于 UserControls 和 WebParts 的 PlaceHolder。此 PlaceHolder 由 PageBuilder 填充。

      我们的 aspx 页面中的 UserControl/WebPart PlaceHolder 可以填充我们想要的任何控件。所以根本不需要改变aspx页面。如果我们想要一个文本框,我们可以配置它。自定义 UserControl 或 WebPart 也是如此。这样我们就不需要为每个自定义应用程序重新创建 aspx 页面,而只需要更改配置即可。

      我们有 100 多个用于各种 aspx 页面的用户控件和 WebPart,但大多数 aspx 页面看起来类似于:

      <%@ Page MasterPageFile="main.master" ... %>
      <asp:Content runat="server" ContentPlaceHolderID="Main" ID="MainSection">
        <asp:PlaceHolder runat="server ID="UserControlPlaceHolder"></asp:PlaceHolder>
      </asp:Content>
      

      在代码隐藏中我们有类似的东西:

      Partial Class MyPageClass Inherits BasePage
        Protected Sub Page_Init(ByVal sender As Object, ByVal e as System.EventArgs) Handles Me.Init
          'The following method is in the BasePage and is part of the PageBuilder.
          LoadControls()
        End Sub
      End Class
      

      PageBuilder 创建布局,然后在正确的位置加载并添加所有控件和 WebPart。
      (布局,哪些控件和控件位置都是从配置中获取的。)

      然后,PageBuilder 为每个控件和 WebPart 应用设置。这些设置也是可配置的。设置可以像控件的高度这样简单,也可以像“显示模式”这样更复杂的东西(静态、页面相关、组相关等)。

      希望这能更详细地解释它。

      【讨论】:

      • 我实际上不想在每个自定义应用程序中重新创建新页面。您的“框架”是否允许使用例如文本框来丰富 aspx 页面,而无需对其进行修改?是 PageBuilder 的角色吗?谁叫那个 Builder ?你能提供一些细节吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-23
      • 1970-01-01
      相关资源
      最近更新 更多