2010-09-07 74 views
5

有沒有人有任何如何使Unity 1.2或2.0與ASP.NET WebForms一起工作的好例子?統一和ASP.NET WebForms - 沒有爲此對象定義的無參數構造函數

我以爲我有這個想法,但顯然我錯過了一些東西。現在我收到了錯誤; 「沒有爲此對象定義無參數的構造函數」。我記得幾年前發生這個錯誤,我只是不記得我做了什麼。

很顯然,Unity並不像它應該那樣工作,因爲在某些地方我已經忘記了一些東西。任何幫助,將不勝感激。

下面是我的一些代碼:

的Global.asax

 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.Security; 
using System.Web.SessionState; 

using Microsoft.Practices.Unity; 

using PIA35.Unity; 

namespace PIA35.Web 
{ 
    public class Global : System.Web.HttpApplication 
    { 

     protected void Application_Start(object sender, EventArgs e) 
     { 
      IUnityContainer container = Application.GetContainer(); 
      PIA35.Web.IoC.Bootstrapper.Configure(container); 
     } 
    } 
} 

這裏是我的HttpModules web.config文件的部分:

 
<httpModules> 
    <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> 
    <add name="UnityHttpModule" type="PIA35.Unity.UnityHttpModule, PIA35.Unity"/> 
</httpModules> 

下面是我的IoC的引導程序類的代碼。

 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using Microsoft.Practices.Unity; 

using PIA35.Services.Interfaces; 
using PIA35.Services; 
using PIA35.DataObjects.Interfaces; 
using PIA35.DataObjects.SqlServer; 

namespace PIA35.Web.IoC 
{ 
    public static class Bootstrapper 
    { 
     public static void Configure(IUnityContainer container) 
     { 
      container 
       .RegisterType<ICategoryService, CategoryService>() 
       .RegisterType<ICustomerService, CustomerService>() 
       .RegisterType<IOrderService, OrderService>() 
       .RegisterType<IOrderDetailService, OrderDetailService>() 
       .RegisterType<IProductService, ProductService>() 
       .RegisterType<ICategoryDao, SqlServerCategoryDao>() 
       .RegisterType<ICustomerDao, SqlServerCustomerDao>() 
       .RegisterType<IOrderDao, SqlServerOrderDao>() 
       .RegisterType<IOrderDetailDao, SqlServerOrderDetailDao>() 
       .RegisterType<IProductDao, SqlServerProductDao>(); 
     } 
    } 
} 

這裏是HttpApplicationStateExtensions.cs文件。

 
using System.Web; 

using Microsoft.Practices.Unity; 

namespace PIA35.Unity 
{ 
    public static class HttpApplicationStateExtensions 
    { 
     private const string GlobalContainerKey = "GlobalUnityContainerKey"; 

     public static IUnityContainer GetContainer(this HttpApplicationState application) 
     { 
      application.Lock(); 
      try 
      { 
       IUnityContainer container = application[GlobalContainerKey] as IUnityContainer; 
       if (container == null) 
       { 
        container = new UnityContainer(); 
        application[GlobalContainerKey] = container; 
       } 
       return container; 
      } 
      finally 
      { 
       application.UnLock(); 
      } 
     } 
    } 
} 

這是我的UnityHttpModule.cs文件。

 
using System; 
using System.Collections.Generic; 
using System.Web; 
using System.Web.UI; 
using Microsoft.Practices.Unity; 

namespace PIA35.Unity 
{ 
    public class UnityHttpModule : IHttpModule 
    { 
     #region IHttpModule Members 

     /// 
     ///Initializes a module and prepares it to handle requests. 
     /// 
     /// 
     ///An 
     ///that provides access to the methods, properties, 
     ///and events common to all application objects within an ASP.NET application 
     public void Init(HttpApplication context) 
     { 
      context.PreRequestHandlerExecute += OnPreRequestHandlerExecute; 
     } 

     /// 
     ///Disposes of the resources (other than memory) 
     ///used by the module that implements . 
     /// 
     /// 
     public void Dispose() 
     { 
     } 

     #endregion 

     private void OnPreRequestHandlerExecute(object sender, EventArgs e) 
     { 
      IHttpHandler handler = HttpContext.Current.Handler; 
      HttpContext.Current.Application.GetContainer().BuildUp(handler.GetType(), handler); 

      // User Controls are ready to be built up after the page initialization is complete 
      Page page = HttpContext.Current.Handler as Page; 
      if (page != null) 
      { 
       page.InitComplete += OnPageInitComplete; 
      } 
     } 

     // Get the controls in the page's control tree excluding the page itself 
     private IEnumerable GetControlTree(Control root) 
     { 
      foreach (Control child in root.Controls) 
      { 
       yield return child; 
       foreach (Control c in GetControlTree(child)) 
       { 
        yield return c; 
       } 
      } 
     } 

     // Build up each control in the page's control tree 
     private void OnPageInitComplete(object sender, EventArgs e) 
     { 
      Page page = (Page)sender; 
      IUnityContainer container = HttpContext.Current.Application.GetContainer(); 
      foreach (Control c in GetControlTree(page)) 
      { 
       container.BuildUp(c.GetType(), c); 
      } 
     } 
    } 
} 

下面是我的一個服務類的示例。

 
namespace PIA35.Services 
{ 
    public class CategoryService : ICategoryService 
    { 

     #region Dependency Injection 

     private ICategoryDao categoryDao; 

     public CategoryService(ICategoryDao CategoryDao) 
     { 
      this.categoryDao = CategoryDao; 
     } 

     #endregion 


     #region ICategoryService Members 

     public List GetAll() 
     { 
      return categoryDao.GetAll().ToList(); 
     } 

     public Category GetById(int CategoryId) 
     { 
      return categoryDao.GetById(CategoryId); 
     } 

     public void Add(Category model) 
     { 
      categoryDao.Insert(model); 
     } 

     public void Update(Category model) 
     { 
      categoryDao.Update(model); 
     } 

     public void Delete(Category model) 
     { 
      categoryDao.Delete(model); 
     } 

     #endregion 
    } 
} 
+0

好的,我發現這實際上有效。我只是用錯了。我試圖將GridView綁定到指向CategoryService類的ObjectDataSource。它似乎不像ObjectDataSource控件可以接口。所以我需要在代碼中做到這一點。好吧。 – Kahanu 2010-09-07 23:38:04

回答

5

我看到它已經回答了,但只是想我要指出的是,你是同步所有的來電GetContainer與你的鎖定模式。對Application.Lock()的調用實際上會在Web應用程序中的單例對象applicationState上取出一個寫鎖定,如果要對其進行縮放,則會看到問題。

要整理這件事,你可以做一個雙重檢查鎖。像這樣:

public static IUnityContainer GetContainer(this HttpApplicationState application) 
    { 
     IUnityContainer container = application[GlobalContainerKey] as IUnityContainer; 
     if (container == null) 
     { 
      application.Lock(); 
      try 
      { 
       container = application[GlobalContainerKey] as IUnityContainer; 
       if (container == null) 
       { 
        container = new UnityContainer(); 
        application[GlobalContainerKey] = container; 
       } 
      } 
      finally 
      { 
       application.UnLock(); 
      } 
     } 
     return container; 
    } 

我還想指出,我們已經使用,以確保控制和網頁有自己的依賴關係建立了一個整潔的格局。我們基本上有一個通用的PageBase和泛型的ControlBase,我們所有的頁面和控件都從它們繼承而來。我剛進入pagebase爲例:

public abstract class SitePageBase<T> : SitePageBase where T : SitePageBase<T> 
{ 
    protected override void OnInit(EventArgs e) 
    { 
     BuildUpDerived(); 
     base.OnInit(e); 
    } 

    protected void BuildUpDerived() 
    { 
     ContainerProvider.Container.BuildUp(this as T); 
    } 
} 

那麼在我們的頁面,我們可以簡單地從通用基礎派生它會看起來積聚後。

public partial class Default : SitePageBase<Default> 
{ 
     [Dependency] 
     public IContentService ContentService { get; set; } 

     protected override void OnPreRender(EventArgs e) 
     { 
      this.label.Text = ContentService.GetContent("labelText"); 
     } 
    } 
2

ObjectDataSource可以帶一個接口,但不能和嚮導一起使用。您可以使用該向導來創建ObjectDataSource標記,然後對其進行編輯並將TypeName屬性值轉換爲您的接口名稱。

然後,您需要指示ObjectDataSource如何創建對象。我使用的方法是處理OnObjectCreating事件,所以在後面的代碼我有:

[Dependency] 
public IMyService Service { get; set; } 

protected void OnObjectCreating(...) 
{ 
    e.ObjectInstance = Service; 
} 
+0

看起來不錯。我不知道這件事。我會試一試。謝謝。 – Kahanu 2010-09-13 00:51:06

1

我有一段時間的工作項目,我開始了一個新的項目,並得到同樣的問題。 做一些比較,並花了我一段時間。但我記得你需要在global.asax中初始化它 。

Bootstrapper.Initialise(); // Missing in the global.asax 
相關問題