Unity 和 ASP.NET WebForms - 没有为此对象定义无参数构造函数 [英] Unity and ASP.NET WebForms - No parameterless constructor defined for this object

查看:37
本文介绍了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{公共类全局:System.Web.HttpApplication{protected void Application_Start(对象发送者,EventArgs e){IUnityContainer 容器 = Application.GetContainer();PIA35.Web.IoC.Bootstrapper.Configure(容器);}}}

这是我的 web.config 文件的 httpModules 部分:

<前><http模块><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 引导程序类的代码.

<前>使用系统;使用 System.Collections.Generic;使用 System.Linq;使用 System.Web;使用 Microsoft.Practices.Unity;使用 PIA35.Services.Interfaces;使用 PIA35.Services;使用 PIA35.DataObjects.Interfaces;使用 PIA35.DataObjects.SqlServer;命名空间 PIA35.Web.IoC{公共静态类引导程序{公共静态无效配置(IUnityContainer容器){容器.RegisterType().RegisterType().RegisterType().RegisterType().RegisterType().RegisterType().RegisterType().RegisterType().RegisterType().RegisterType();}}}

这是 HttpApplicationStateExtensions.cs 文件.

<前>使用 System.Web;使用 Microsoft.Practices.Unity;命名空间 PIA35.Unity{公共静态类 HttpApplicationStateExtensions{private const string GlobalContainerKey = "GlobalUnityContainerKey";公共静态 IUnityContainer GetContainer(这个 HttpApplicationState 应用程序){application.Lock();尝试{IUnityContainer container = application[GlobalContainerKey] as IUnityContainer;如果(容器 == 空){容器 = 新的 UnityContainer();应用程序[GlobalContainerKey] = 容器;}返回容器;}最后{application.UnLock();}}}}

这是我的 UnityHttpModule.cs 文件.

<前>使用系统;使用 System.Collections.Generic;使用 System.Web;使用 System.Web.UI;使用 Microsoft.Practices.Unity;命名空间 PIA35.Unity{公共类 UnityHttpModule : IHttpModule{#region IHttpModule 成员//////初始化一个模块并准备它来处理请求./////////一个///提供对方法、属性的访问,///和 ASP.NET 应用程序中所有应用程序对象共有的事件公共无效初始化(HttpApplication上下文){context.PreRequestHandlerExecute += OnPreRequestHandlerExecute;}//////处理资源(内存除外)///由实现 .//////公共无效处置(){}#endregionprivate void OnPreRequestHandlerExecute(对象发送者,EventArgs e){IHttpHandler 处理程序 = HttpContext.Current.Handler;HttpContext.Current.Application.GetContainer().BuildUp(handler.GetType(), handler);//页面初始化完成后就可以建立用户控件了Page page = HttpContext.Current.Handler as Page;如果(页面!= null){page.InitComplete += OnPageInitComplete;}}//获取页面控件树中不包括页面本身的控件私有 IEnumerable GetControlTree(控件根){foreach(在 root.Controls 中控制子级){yield return child;foreach (GetControlTree(child) 中的 Control c){收益率c;}}}//在页面的控件树中建立每个控件私有无效 OnPageInitComplete(对象发送者,EventArgs e){页面页面 = (Page)sender;IUnityContainer 容器 = HttpContext.Current.Application.GetContainer();foreach(GetControlTree(page) 中的 Control c){container.BuildUp(c.GetType(), c);}}}}

这是我的一个服务类的示例.

<前>命名空间 PIA35.Services{公共类 CategoryService :ICategoryService{#region 依赖注入私有ICategoryDao categoryDao;公共类别服务(ICategoryDao CategoryDao){this.categoryDao = CategoryDao;}#endregion#region ICategoryService 成员公共列表 GetAll(){返回 categoryDao.GetAll().ToList();}公共类别 GetById(int CategoryId){返回 categoryDao.GetById(CategoryId);}公共无效添加(类别模型){categoryDao.Insert(模型);}公共无效更新(类别模型){categoryDao.Update(model);}公共无效删除(类别模型){categoryDao.Delete(模型);}#endregion}}

解决方案

我看到已经有人回答了,但我只是想指出您正在将所有对 GetContainer 的调用与您的锁定模式同步.对 Application.Lock() 的调用实际上会在 applicationState 上取出一个写锁,它是您的 Web 应用程序中的一个单例对象,如果您想扩展它,您会看到问题.

为了解决这个问题,你可以做一个双重检查的锁.像这样:

 public static IUnityContainer GetContainer(这个HttpApplicationState应用程序){IUnityContainer container = application[GlobalContainerKey] as IUnityContainer;如果(容器 == 空){application.Lock();尝试{container = application[GlobalContainerKey] as IUnityContainer;如果(容器 == 空){容器 = 新的 UnityContainer();应用程序[GlobalContainerKey] = 容器;}}最后{application.UnLock();}}返回容器;}

我还想指出一个简洁的模式,我们用来确保控件和页面建立了它们的依赖关系.我们基本上有一个 Generic PageBase 和 Generic ControlBase,我们所有的页面和控件都继承自它们.我将进入页面库作为示例:

公共抽象类 SitePageBase:SitePageBase 其中 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{[依赖]公共 IContentService ContentService { 获取;放;}protected override void OnPreRender( EventArgs e ){this.label.Text = ContentService.GetContent("labelText");}}

Does anyone have any good examples of how to make Unity 1.2 or 2.0 work with ASP.NET WebForms?

I thought I had this figured out, but evidently I'm missing something. Now I'm getting the error; "No parameterless constructor defined for this object". I remember getting this error a couple years ago, I and just don't remember what I did.

Obviously Unity isn't working as it should because somewhere along the way I've forgotten something. Any help would be appreciated.

Here's some of my code:

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);
        }
    }
}

Here's my httpModules section of the web.config file:

<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>

Here's the code for my IoC bootstrapper class.

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>();
        }
    }
}

Here's the HttpApplicationStateExtensions.cs file.

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();
            }
        }
    }
}

Here's my UnityHttpModule.cs file.

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);
            }
        }
    }
}

Here's an example of one of my service classes.

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
    }
}

解决方案

I see it has already been answered but just thought I would point out that you are synchronising all the calls to GetContainer with your locking pattern. A call to Application.Lock() actually takes out a write lock on the applicationState which is a singleton object in your web application and you will see issues if you want to scale this.

To tidy this up you could do a double checked lock. like this:

    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;
    }

I would also like to point out a neat pattern that we have used to ensure Controls and Pages have their Dependencies built up. We basically have a Generic PageBase and Generic ControlBase that all our pages and controls inherit from. I will just go into the pagebase as an example:

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 );
    }
}

Then in our Pages we can simply derive from Generic base and it will look after the build up.

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

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

这篇关于Unity 和 ASP.NET WebForms - 没有为此对象定义无参数构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆