# IT:AD:NET:IoC:Unity:HttpContextLifetimeManager # * [[../|(UP)]] {{indexmenu>.#2|nsort tsort}} ## Situation ## Incredibly, Unity only offers a Thread based lifetime manager -- which is not appropriate for Web Scenarios. ## Solution ## Either use Ninject (as it has one baked in), or use the following when registering Services. Code: using System; using System.Collections; using System.Collections.Generic; using System.Reflection; using Microsoft.Practices.Unity; namespace XAct.Services.IoC { /// /// An implementation of the Unity Lifetime Manager specifically for /// Web scenarios. /// /// /// /// Used by when /// trying to register services by WebRequest. /// /// /// /// See: http://bit.ly/yyguHs /// public class HttpContextLifetimeManager : PerThreadLifetimeManager, IDisposable { private readonly string _key = Guid.NewGuid().ToString(); #region Constants /// /// Class of constants used within the /// /// class. /// public static class Constants { /// /// Constant used to save the ApplicationName in the Request's hashtable. /// public const string ApplicationNameKey = "ApplicationName"; /// /// FQN of System.Web /// public const string SystemWebAssemblyString = "System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"; } #endregion /// /// Retrieve a value from the backing store associated with this Lifetime policy. /// /// /// the object desired, or null if no such object is currently stored. /// public override object GetValue() { if (HttpContext == null) { return base.GetValue(); } return InnerDict[_key]; } /// /// Remove the given object from backing store. /// public override void RemoveValue() { if (HttpContext==null) { base.RemoveValue(); return; } InnerDict.Remove(_key); } /// /// Stores the given value into backing store for retrieval later. /// /// The object being stored. public override void SetValue(object newValue) { if (HttpContext == null) { base.SetValue(newValue); } InnerDict[_key] = newValue; } /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { RemoveValue(); } private IDictionary InnerDict { get { const string key = "Unity.HttpContextLifetimeManager.Cache"; IDictionary results = HttpContextItems[key] as IDictionary; if (results == null) { results = new Dictionary(); HttpContextItems.Add(key, results); } return results; } } /// /// The HttpContext by Reflection /// (so that this assembly does not end up having a reference /// to System.Web) /// public static object HttpContext { get { if (_cachedHttpContextPropertyInfo == null) { const string path = "System.Web.HttpContext"; const string assemblyName = Constants.SystemWebAssemblyString; const string contextPath = "Current"; Type type = Type.GetType(path + ", " + assemblyName, true, true); if (type == null) { return null; } //get the HTTP context property info _cachedHttpContextPropertyInfo = type.GetProperty(contextPath, (BindingFlags.Public | BindingFlags.Static)); } //get a reference to the current HTTP context return _cachedHttpContextPropertyInfo.GetValue(null, null); } } private static PropertyInfo _cachedHttpContextPropertyInfo; /// /// Gets the items. /// public IDictionary HttpContextItems { get { if (HttpContext != null) { IDictionary items = HttpContext.GetValue("Items") as IDictionary; return items; } throw new Exception("No HttpContext to back HttpContextLifetimeManager"); } } } }