首页 文章

Unity和ASP.NET WebForms - 没有为此对象定义的无参数构造函数

提问于
浏览
5

有没有人有任何关于如何使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
    }
}

3 回答

  • 1

    我看到它已经得到了解答,但我想我会指出你正在使用锁定模式同步所有对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;
        }
    

    我还想指出一个简洁的模式,我们已经用它来确保控件和页面的依赖关系 Build 起来 . 我们基本上有一个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");
            }
         }
    
  • 2

    ObjectDataSource可以使用接口,但不能使用向导 . 您可以使用向导创建ObjectDataSource标记,然后编辑它并将TypeName属性值转换为您的接口名称 .

    然后,您需要指示ObjectDataSource如何创建对象 . 我正在使用的方法是处理OnObjectCreating事件,所以在后面的代码我有:

    [Dependency]
    public IMyService Service { get; set; }
    
    protected void OnObjectCreating(...)
    {
       e.ObjectInstance = Service;
    }
    
  • 6

    我有一个工作项目,我开始一个新的项目,并得到同样的问题 . 做一些比较并带我一段时间 . 但我记得你需要在global.asax中初始化它 .

    Bootstrapper.Initialise(); // Missing in the global.asax
    

相关问题