Comment utiliser Château de Windsor avec ASP.Net formulaires web?
Je suis en train de câbler l'injection de dépendance avec les Windsor à la norme asp.net les formulaires web. Je crois que j'ai atteint ce à l'aide d'un HttpModule et un CustomAttribute (code indiqué ci-dessous), bien que la solution me semble un peu maladroit, et je me demandais si il y a une meilleure solution de prise en charge hors de la boîte avec les Windsor?
Il y a plusieurs fichiers tous représentés ici
//index.aspx.cs
public partial class IndexPage : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Logger.Write("page loading");
}
[Inject]
public ILogger Logger { get; set; }
}
//WindsorHttpModule.cs
public class WindsorHttpModule : IHttpModule
{
private HttpApplication _application;
private IoCProvider _iocProvider;
public void Init(HttpApplication context)
{
_application = context;
_iocProvider = context as IoCProvider;
if(_iocProvider == null)
{
throw new InvalidOperationException("Application must implement IoCProvider");
}
_application.PreRequestHandlerExecute += InitiateWindsor;
}
private void InitiateWindsor(object sender, System.EventArgs e)
{
Page currentPage = _application.Context.CurrentHandler as Page;
if(currentPage != null)
{
InjectPropertiesOn(currentPage);
currentPage.InitComplete += delegate { InjectUserControls(currentPage); };
}
}
private void InjectUserControls(Control parent)
{
if(parent.Controls != null)
{
foreach (Control control in parent.Controls)
{
if(control is UserControl)
{
InjectPropertiesOn(control);
}
InjectUserControls(control);
}
}
}
private void InjectPropertiesOn(object currentPage)
{
PropertyInfo[] properties = currentPage.GetType().GetProperties();
foreach(PropertyInfo property in properties)
{
object[] attributes = property.GetCustomAttributes(typeof (InjectAttribute), false);
if(attributes != null && attributes.Length > 0)
{
object valueToInject = _iocProvider.Container.Resolve(property.PropertyType);
property.SetValue(currentPage, valueToInject, null);
}
}
}
}
//Global.asax.cs
public class Global : System.Web.HttpApplication, IoCProvider
{
private IWindsorContainer _container;
public override void Init()
{
base.Init();
InitializeIoC();
}
private void InitializeIoC()
{
_container = new WindsorContainer();
_container.AddComponent<ILogger, Logger>();
}
public IWindsorContainer Container
{
get { return _container; }
}
}
public interface IoCProvider
{
IWindsorContainer Container { get; }
}
- Je voudrais juste dire merci pour le code ci-dessus car il m'a permis de créer un MVP cadre de certains anciens webforms code.
- Pas un problème Keith.. content que ça pourrait être utile à quelqu'un
- j'ai essayé ce code, mais il efface le ViewState sur chaque demande. Il semble que si vous accédez à la propriété Controls de la Page en cours avant l'événement de Chargement, ASP.NET est incapable de restaurer l'état d'affichage lors de la LoadViewState étape entre l'Initialisation et de Chargement (voir forums.asp.net/p/1043999/1537884.aspx). Je crois que c'est pourquoi Ayende utilise l'événement Init de base de classes pour la Page d', MasterPage, et UserControl, respectivement, pour résoudre tout Cio dépendances.
- intéressant.. merci pour la mise à jour. En fait, j'ai été en utilisant la méthode que vous décrivez après les conseils ci-dessous pour regarder igloo.
Vous devez vous connecter pour publier un commentaire.
Je pense que vous êtes fondamentalement sur la bonne voie Si vous ne l'avez pas déjà, je voudrais suggérer de prendre un coup d'oeil à Rhino Igloo, un WebForms framework MVC, Voici un bon article de blog sur ce et la source est ici - Ayende (l'Auteur de Rhino Igloo) aborde la question de l'utilisation de Windsor avec les formulaires web assez bien dans ce projet/bibliothèque.
Je cache la réflexion info si vous allez injecter la totalité de l'ensemble imbriqué de contrôle, qui pourrait finir par être un peu de rendement, d'un porc, je soupçonne.
Le dernier de tous spring.net des approches de plus en plus de la configuration axée sur la, mais il pourrait être la peine de prendre un coup d'oeil à leur mise en œuvre - voici un bon référence post de blog sur ce.
Voici une version modifiée de l'OP du code que (i) les caches injecté propriétés d'éviter la répétition de réflexion appels, (ii) les communiqués de tous les composants résolus, (iii) encapsule l'accès au conteneur de façon à ne pas exposer la mise en œuvre.
J'ai récemment commencé à une société où il y a beaucoup d'anciens webform apps, ce qui semble être une véritable approche intéressante, et pourrait offrir une voie à suivre si nous voulons ajouter des DI à des pages web existantes, merci.
Un moment, j'ai remarqué, c'est que la méthode d'Injection utilise le conteneur.Résoudre à résoudre explicitement les composants, donc je pense que nous avons peut-être besoin de faire un conteneur.Communiqué sur les composants lorsque la Page Décharge.
Si nous avons transitoire de composants et de ne pas faire cela, alors on peut faire face à des fuites de mémoire. Pas sûr de savoir comment les composants avec Par Web Demande de modes de vie allait se comporter (c'est à dire aurait Windsor ramasser à la fin de la requête web, même si nous avons explicitement résolu), mais ici aussi, peut voulez jouer la sécurité.
Par conséquent, le module peut avoir besoin d'être étendu à garder la trace des composants qu'elle n'en résout et de les libérer afin qu'Windsor sait quand à nettoyer.
Une chose qui manquait dans les réponses acceptées a été le fait que le module http doit être enregistrée dans le web.fichier de configuration (selon l'application) avant que le module sera réellement résoudre les dépendances sur les pages code-behind. Ce que vous avez besoin est :
Autres que les solutions acceptées travaillé comme un charme.
Référence au site web de Microsoft pour l'ajout de modules http: https://msdn.microsoft.com/en-us/library/ms227673.aspx
Plutôt que de le faire comme cela, vous pouvez également utiliser un type de résolveur directement avec quelque chose comme: