Unity和ASP.NET WebForms – 没有为此对象定义的无参数构造函数
有没有人有任何关于如何使Unity 1.2或2.0与ASP.NET WebForms一起工作的好例子?
我以为我弄明白了,但显然我错过了一些东西。 现在我收到了错误; “没有为此对象定义无参数构造函数”。 我记得几年前收到这个错误,我只是不记得我做了什么。
显然Unity并没有按照它应有的方式运作,因为我忘记了某些事情。 任何帮助,将不胜感激。
这是我的一些代码:
Global.asax中
使用系统; 使用System.Collections.Generic; 使用System.Linq; 使用System.Web; 使用System.Web.Security; 使用System.Web.SessionState; 使用Microsoft.Practices.Unity; 使用PIA35.Unity; 命名空间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(容器); } } }
这是web.config文件的httpModules部分:
这是我的IoC bootstrapper类的代码。
使用系统; 使用System.Collections.Generic; 使用System.Linq; 使用System.Web; 使用Microsoft.Practices.Unity; 使用PIA35.Services.Interfaces; 使用PIA35.Services; 使用PIA35.DataObjects.Interfaces; 使用PIA35.DataObjects.SqlServer; 命名空间PIA35.Web.IoC { public static class Bootstrapper { public static void Configure(IUnityContainer容器) { 容器 .RegisterType () .RegisterType () .RegisterType () .RegisterType () .RegisterType () .RegisterType () .RegisterType () .RegisterType () .RegisterType () .RegisterType (); } } }
这是HttpApplicationStateExtensions.cs文件。
使用System.Web; 使用Microsoft.Practices.Unity; 名称空间PIA35.Unity { public static class HttpApplicationStateExtensions { private const string GlobalContainerKey =“GlobalUnityContainerKey”; public static IUnityContainer GetContainer(这个HttpApplicationState应用程序) { application.Lock(); 尝试 { IUnityContainer container = application [GlobalContainerKey] as IUnityContainer; if(container == null) { container = new UnityContainer(); application [GlobalContainerKey] = container; } 回收容器; } 最后 { application.UnLock(); } } } }
这是我的UnityHttpModule.cs文件。
使用系统; 使用System.Collections.Generic; 使用System.Web; 使用System.Web.UI; 使用Microsoft.Practices.Unity; 名称空间PIA35.Unity { 公共类UnityHttpModule:IHttpModule { #region IHttpModule成员 /// ///初始化模块并准备处理请求。 /// /// ///一个 ///提供对方法,属性的访问, ///和ASP.NET应用程序中所有应用程序对象共有的事件 public void Init(HttpApplication context) { context.PreRequestHandlerExecute + = OnPreRequestHandlerExecute; } /// ///配置资源(内存除外) ///由实现的模块使用。 /// /// public void Dispose() { } #endregion private void OnPreRequestHandlerExecute(object sender,EventArgs e) { IHttpHandler handler = HttpContext.Current.Handler; HttpContext.Current.Application.GetContainer()。BuildUp(handler.GetType(),handler); //页面初始化完成后,就可以构建用户控件了 Page page = HttpContext.Current.Handler as Page; if(page!= null) { page.InitComplete + = OnPageInitComplete; } } //获取页面控制树中的控件,不包括页面本身 private IEnumerable GetControlTree(Control root) { foreach(在root.Controls中控制孩子) { 屈服回报孩子; foreach(GetControlTree(child)中的控件c) { 收益率c; } } } //在页面的控制树中构建每个控件 private void OnPageInitComplete(object sender,EventArgs e) { 页面=(页面)发件人; IUnityContainer container = HttpContext.Current.Application.GetContainer(); foreach(GetControlTree中的控件c(页面)) { container.BuildUp(c.GetType(),c); } } } }
这是我的一个服务类的示例。
命名空间PIA35.Services { 公共类CategoryService:ICategoryService { #regiondependency injection 私人ICategoryDao类别; public CategoryService(ICategoryDao CategoryDao) { this.categoryDao = CategoryDao; } #endregion #region ICategoryService成员 公开列表GetAll() { return categoryDao.GetAll()。ToList(); } 公共类别GetById(int CategoryId) { return categoryDao.GetById(CategoryId); } public void Add(Category model) { categoryDao.Insert(模型); } public void Update(分类型号) { categoryDao.Update(模型); } public void删除(类别模型) { categoryDao.Delete(模型); } #endregion } }
我看到它已经得到了回答,但我想我会指出你正在使用锁定模式同步所有对GetContainer的调用。 对Application.Lock()的调用实际上会在applicationState上取出一个写锁定,它是Web应用程序中的单个对象,如果要扩展它,您将看到问题。
要整理一下,你可以做一个双重检查锁。 像这样:
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; }
我还想指出一个简洁的模式,我们已经用它来确保控件和页面的依赖关系建立起来。 我们基本上有一个Generic PageBase和Generic ControlBase,我们所有的页面和控件都inheritance自。 我将以页面库为例进行说明:
public abstract class SitePageBase : SitePageBase where T : SitePageBase { protected override void OnInit( EventArgs e ) { BuildUpDerived(); base.OnInit( e ); } protected void BuildUpDerived() { ContainerProvider.Container.BuildUp( this as T ); } }
然后在我们的页面中,我们可以简单地从Generic base派生,它将负责构建。
public partial class Default : SitePageBase { [Dependency] public IContentService ContentService { get; set; } protected override void OnPreRender( EventArgs e ) { this.label.Text = ContentService.GetContent("labelText"); } }
ObjectDataSource可以使用接口,但不能使用向导。 您可以使用该向导创建ObjectDataSource标记,然后对其进行编辑,并将TypeName属性值转换为您的接口名称。
然后,您需要指示ObjectDataSource如何创建对象。 我正在使用的方法是处理OnObjectCreating事件,所以在后面的代码我有:
[Dependency] public IMyService Service { get; set; } protected void OnObjectCreating(...) { e.ObjectInstance = Service; }
我有一段时间有一个工作项目,我开始了一个新项目并遇到了同样的问题。 做一些比较,并花了我一段时间。 但我记得你需要在global.asax中初始化它。
Bootstrapper.Initialise(); // Missing in the global.asax