2010-09-07 16 views
5

¿Alguien tiene algún buen ejemplo de cómo hacer que Unity 1.2 o 2.0 funcione con ASP.NET WebForms?WebForms de Unity y ASP.NET: no se ha definido ningún constructor sin parámetros para este objeto

Pensé que tenía esto resuelto, pero evidentemente me falta algo. Ahora estoy obteniendo el error; "Ningún constructor sin parámetros definido para este objeto". Recuerdo haber recibido este error hace un par de años, y simplemente no recuerdo lo que hice.

Obviamente Unity no funciona como debería porque en algún punto del camino he olvidado algo. Cualquier ayuda sería apreciada.

He aquí algunos de mi código:

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

Aquí es mi sección httpModules del archivo 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> 

Aquí está el código para mi clase de programa previo COI .

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

Aquí está el archivo 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(); 
      } 
     } 
    } 
} 

Aquí está mi archivo 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); 
      } 
     } 
    } 
} 

Aquí hay un ejemplo de una de mis clases de servicio.

 
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

Ok, me di cuenta de que esto realmente funciona. Solo lo estoy usando mal Estoy intentando vincular un GridView a un ObjectDataSource que apunta a la clase CategoryService. No parece que el control ObjectDataSource pueda tomar una interfaz. Entonces necesito hacer esto en código. Oh bien. – Kahanu

Respuesta

5

veo que ya ha sido contestada, pero sólo pensaba que iba a señalar que está sincronizando todas las llamadas a GetContainer con su patrón de bloqueo. Una llamada a Application.Lock() realmente saca un bloqueo de escritura en el applicationState que es un objeto singleton en su aplicación web y verá problemas si desea escalar esto.

Para ponerlo en orden, podría hacer un doble bloqueo comprobado. de esta manera:

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

También me gustaría señalar un patrón ordenado que hemos utilizado para garantizar los controles y las páginas tienen sus dependencias construidas. Básicamente, tenemos una Base de datos genérica y una Base de control genérica heredadas de todas nuestras páginas y controles. Sólo voy a entrar en el pagebase como ejemplo:

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

Luego, en nuestras páginas simplemente puede derivar de base genérica y se verá después de la acumulación.

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 puede tomar una interfaz, pero no con el asistente. Puede usar el asistente para crear la etiqueta ObjectDataSource, editarla y convertir el valor del atributo TypeName en su nombre de interfaz.

Luego, debe indicar a ObjectDataSource cómo crear el objeto. La forma en que estoy usando es para controlar el evento OnObjectCreating, por lo que en el código subyacente que tengo:

[Dependency] 
public IMyService Service { get; set; } 

protected void OnObjectCreating(...) 
{ 
    e.ObjectInstance = Service; 
} 
+0

Se ve bien. No sabía sobre esto. Lo probaré. Gracias. – Kahanu

1

Hace un tiempo tuve un proyecto de trabajo y comencé un nuevo proyecto y tuve el mismo problema. Haz una comparación y me tomó un tiempo. Pero recordé que debe inicializarlo en el archivo global.asax.

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