Singleton Par le Contexte d'Appel (Demande Web) dans l'Unité
Il y A quelques jours j'ai eu ce problème avec ASP.Net le filetage. Je voulais avoir un objet singleton par requête web. J'ai réellement besoin de cela pour mon unité de travail. Je voulais instancier une unité de travail par requête web, de sorte que la carte d'identité est valable jusqu'à la demande. De cette façon, je pourrais utiliser un Cio à injecter mon propre IUnitOfWork à mes classes de dépôt de manière transparente, et j'ai pu utiliser la même instance à la requête, puis mise à jour de mes entités.
Depuis que je suis à l'aide de l'Unité, j'ai utilisé à tort PerThreadLifeTimeManager. J'ai vite réalisé que l'ASP.Net modèle de thread ne prend pas en charge ce que je veux atteindre. Fondamentalement, il utilise un theadpool et recycle les threads, et cela signifie que je reçois un UnitOfWork par thread!! Cependant, ce que je voulais, c'était une unité de travail par requête web.
Un peu de recherche sur google m'a donné ce post très. C'est exactement ce que je voulais, sauf pour l'unité de la partie qui était assez facile à réaliser.
C'est ma mise en œuvre pour PerCallContextLifeTimeManager de l'unité:
public class PerCallContextLifeTimeManager : LifetimeManager
{
private const string Key = "SingletonPerCallContext";
public override object GetValue()
{
return CallContext.GetData(Key);
}
public override void SetValue(object newValue)
{
CallContext.SetData(Key, newValue);
}
public override void RemoveValue()
{
}
}
Et bien sûr, je l'utilise pour enregistrer mon unité de travail avec un code similaire à ceci:
unityContainer
.RegisterType<IUnitOfWork, MyDataContext>(
new PerCallContextLifeTimeManager(),
new InjectionConstructor());
Espère qu'il sauve quelqu'un un peu de temps.
- Solution sympa. Si vous me le permettez, je vous recommande de renommer ce "CallContextLifetimeManager" depuis requêtes Web sont probablement l'une des applications potentielles.
- Vrai, j'ai mis à jour le texte et le code pour le refléter. Merci.
- +1 Très utile.
- Quel est le problème avec l'aide de PerResolveLifetimeManager?
- Ce n'est pas une question!?
- Pour info, ce n'est pas la "bonne" réponse/solution à ce problème. Dans ASP.NET une seule demande peut (et souvent sera en charge lourde) de saut entre les threads. Quand il le fait, le CallContext n'est pas reporté, et seul le HttpContext de la migration. Si vous voulez que cela fonctionne dans ASP.NET de façon fiable (sous charge) vous avez besoin de changer CallContext à HttpContext.Actuel.Les éléments de la place.
Vous devez vous connecter pour publier un commentaire.
Solution élégante, mais chaque instance de LifetimeManager doit utiliser une clé unique, plutôt qu'une constante:
Sinon, si vous avez plus d'un objet enregistré avec PerCallContextLifeTimeManager, qu'ils partagent la même clé pour accéder CallContext, et vous ne recevez pas votre objet attendu en retour.
Également intéressant de mise en œuvre de RemoveValue pour assurer les objets sont nettoyés:
CallContext
n'est pas conservé pour une seule requête.Tout c'est très bien, l'appel de cette PerCallContextLifeTimeManager, je suis sûr que c'est pas "coffre-fort" pour être considéré comme un ASP.Net Par demande LifeTimeManager.
Si ASP.Net ne son thread-swap puis le seule chose prises à travers le nouveau fil à travers CallContext est l'actuel HttpContext - rien d'autre que vous stockez dans CallContext aura disparu. Cela signifie que sous une lourde charge le code ci-dessus pourrait avoir des résultats inattendus - et j'imagine que ce serait une vraie douleur pour traquer pourquoi!
La seule "sécurité" façon de le faire est avec HttpContext.Actuel.Les éléments, ou de faire quelque chose comme:
De toute évidence, cela signifie prendre des dépendances sur le Système.Web 🙁
Beaucoup plus d'informations sur cette disponible à:
http://piers7.blogspot.com/2005/11/threadstatic-callcontext-and_02.html
Merci pour votre contribution,
Mais la question de la mise en œuvre proposée a deux inconvénients, dont l'une est un bug grave comme déjà indiqué par Steven Robbins dans réponse et Michée Zoltu dans un commentaire.
Actuellement, L'Unité.Mvc Nuget package fournit un
PerRequestLifetimeManager
pour faire le travail. N'oubliez pas d'enregistrer ses associésUnityPerRequestHttpModule
dans l'amorçage de code sinon libérer des dépendances ne seront pas traitées.À l'aide d'amorçage
ou dans le web.config
system.webServer/modules
Il semble que sa mise en œuvre actuelle est également adapté pour les formulaires web. Et il n'a même pas dépendre MVC. Malheureusement, son assemblée n'a, en raison de certaines autres classes qu'il contient.
Attention, dans le cas où vous utilisez un module http personnalisé à l'aide de votre résolus dépendances, ils ont peut-être déjà disposé dans le module
EndRequest
. Il dépend de l'exécution du module de commande.