2009-11-20 78 views
5

我需要构建一个'可定制的'asp.net web应用程序(而不是asp.net mvc)。依赖注入:在aspx页面注入用户控件

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

有没有人试过?

总之这里是我认为这是可以实现的:

  • 我用斯科特Guthrie的方法来建立一个可重复使用的“用户控件库”(看他的文章“创建和使用用户控件库”) 。

  • 控制和在该库中的页面应当具有的地方动态接收用户控件(例如,在一个asp占位符)。

  • 在我的自定义Web应用程序,建立在库顶,我创建特定的用户控件。

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

就是这样。

这基本上是什么都可以用Spring.Net做如下http://blogger.forgottenskies.com/?p=70但截获用户控件的讨论。

有没有人在这些东西的一些经验?或者它听起来很愚蠢?备择方案 ?

的想法是要建立在我的“用户控件库”的顶部不同的Web应用程序,而不会影响库的可能性。

例如:在我的图书馆我有一个页面有4个文本框和一个特定的应用程序,我需要添加一个文本框,在不改变页面的代码。我们的想法是在该页面放置一个占位符,并在此占位符中动态注入我的自定义文本框。

回答

1

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

一切都是可配置的(页面布局,页面控件,控制位置等),所以没有必要更改页面,用户控件或任何的WebParts代码。 (除非需要添加/更改某些功能)。

我们甚至有控制内配置和设置取决于像SQL查询模式,当前页面等

Basicly它是这样工作的各种事情来改变自己的行为:

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

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

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

您的模型似乎是我们模型的一个子集,我只能说这很容易处理。无论是从开发者角度还是从客户角度来看。

编辑:
Basicly我们的框架包含了一下母版页和基页它调用PageBuilder的。
每个主页面用于不同类型的对象:页面,用户控件,Web部件,灯箱等。
每个aspx页面包含用于UserControls和WebParts的PlaceHolder。这个PlaceHolder由PageBuilder填充。

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

我们有100多个用户控件,并为的WebParts各种aspx页面,但大多数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创建布局然后加载并添加所有控件和WebParts在正确的位置。
(布局,其控制和控制位置都从配置中获取)。

然后,PageBuilder将应用每个Control和WebPart的设置。这些设置也是可配置的。设置可以像控件的高度或“显示模式”(静态,页面依赖,组依赖等)这样的更复杂的事情一样简单。

希望这可以更详细地解释它。

+0

我其实不想在每个自定义应用程序中重新创建新页面。您的“框架”是否允许使用例如文本框丰富aspx页面而不需要修改它?它是否是PageBuilder的角色?谁称之为Builder?你能提供一些细节吗? – Thierry 2009-11-20 08:12:20

4

这与您的情况并不完全相同,但我需要动态注入编辑器控件,具体取决于正在编辑的实体的运行时类型。我有我的所有控件从一个公共接口继承这样的:

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容器(StructureMap在这种情况下)我可以得到一些正确的用户控制像

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配置中的任意位置更改它。