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