2010-09-07 10 views
5

Qualcuno ha qualche buon esempio di come rendere Unity 1.2 o 2.0 compatibile con Web Form di ASP.NET?Unity e ASP.NET WebForms - Nessun costruttore parametrico definito per questo oggetto

Pensavo di averlo capito, ma evidentemente mi manca qualcosa. Ora sto ricevendo l'errore; "Nessun costruttore senza parametri definito per questo oggetto". Ricordo di aver ricevuto questo errore un paio di anni fa, e proprio non ricordo cosa ho fatto.

Ovviamente Unity non funziona come dovrebbe, perché da qualche parte lungo la strada ho dimenticato qualcosa. Qualsiasi aiuto sarebbe apprezzato.

Ecco alcuni del mio codice:

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

Ecco la mia httpModules sezione del file 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> 

Ecco il codice per la mia classe di avvio automatico IOC .

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

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

Ecco il mio file 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); 
      } 
     } 
    } 
} 

Ecco un esempio di una delle mie classi di servizio.

 
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, ho capito che questo funziona davvero. Lo sto solo usando male. Sto cercando di associare un GridView a un oggetto ObjectDataSource che punta alla classe CategoryService. Non sembra che il controllo ObjectDataSource possa prendere un'interfaccia. Quindi ho bisogno di farlo in codice. Oh bene. – Kahanu

risposta

5

vedo io è già stato risposto, ma solo pensato vorrei ricordare che si sincronizza tutte le chiamate a GetContainer con il tuo schema di chiusura. Una chiamata a Application.Lock() in realtà elimina un blocco di scrittura su applicationState che è un oggetto singleton nella tua applicazione web e vedrai problemi se vuoi ridimensionarlo.

Per mettere in ordine questo si può fare un doppio blocco di controllo. in questo modo:

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

Vorrei anche far notare un modello pulito che abbiamo usato per garantire i controlli e le pagine hanno le loro dipendenze costruito. Fondamentalmente abbiamo una basebase generica e una base di controllo generica da cui ereditano tutte le nostre pagine e controlli. Mi limiterò a andare in pagebase come esempio:

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

Poi nelle nostre pagine ci si può semplicemente derivare dalla base generico e sembrerà dopo l'accumulo.

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

L'ObjectDataSource può prendere un'interfaccia, ma non con la procedura guidata. È possibile utilizzare la procedura guidata per creare il tag ObjectDataSource, quindi modificarlo e trasformare il valore dell'attributo TypeName nel nome dell'interfaccia.

Quindi, è necessario istruire ObjectDataSource su come creare l'oggetto. Il modo in cui sto usando è quello di gestire l'evento OnObjectCreating, quindi nel codice dietro ho:

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

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

Sembra buono. Non lo sapevo. Lo proverò. Grazie. – Kahanu

1

ho avuto un progetto di lavoro un po 'indietro e ho iniziato un nuovo progetto e ottenere lo stesso problema. Fai qualche confronto e mi ci è voluto un po '. Ma mi sono ricordato che è necessario inizializzare lo nel global.asax.

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