有没有人有任何关于如何使Unity 1.2或2.0与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); } } }
这是web.config文件的httpModules部分:
<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 bootstrapper类的代码。
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 :(得分:6)
我看到它已经被回答,但我想我会指出你正在使用锁定模式同步所有对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,我们所有的页面和控件都继承自。我将以页面库为例:
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 );
}
}
然后在我们的页面中,我们可以简单地从Generic base派生出来,它将负责构建。
public partial class Default : SitePageBase<Default>
{
[Dependency]
public IContentService ContentService { get; set; }
protected override void OnPreRender( EventArgs e )
{
this.label.Text = ContentService.GetContent("labelText");
}
}
答案 1 :(得分:2)
ObjectDataSource可以使用接口,但不能使用向导。您可以使用向导创建ObjectDataSource标记,然后编辑它并将TypeName属性值转换为您的接口名称。
然后,您需要指示ObjectDataSource如何创建对象。我正在使用的方法是处理OnObjectCreating事件,所以在后面的代码中我有:
[Dependency]
public IMyService Service { get; set; }
protected void OnObjectCreating(...)
{
e.ObjectInstance = Service;
}
答案 2 :(得分:1)
我有一段时间有一个工作项目,我开始了一个新项目并遇到了同样的问题。 做一些比较并带我一段时间。但我记得你需要初始化 它在global.asax。
Bootstrapper.Initialise(); // Missing in the global.asax