2010-09-07 72 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 
相关问题