Skip to content

Instantly share code, notes, and snippets.

@randyburden
Last active December 10, 2015 08:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save randyburden/4406029 to your computer and use it in GitHub Desktop.
Save randyburden/4406029 to your computer and use it in GitHub Desktop.
Abstracts away the application's underlying storage context allowing you to simply call Get() or Store() and it will store the data in the appropriate context. It makes use of reflection too so that there is no need to reference the System.Web assembly if the application doesn't need it. For ASP.NET applications, it will store in the data in the…
/// <summary>
/// Provides a means of getting/storing data in the host application's
/// appropriate context.
/// </summary>
/// <remarks>
/// For ASP.NET applications, it will store in the data in the current HTTPContext.
/// For all other applications, it will store the data in the logical call context.
/// </remarks>
public static class ContextStorage
{
/// <summary>
/// Get a stored item.
/// </summary>
/// <typeparam name="T">Object type</typeparam>
/// <param name="key">Item key</param>
/// <returns>Reference to the requested object</returns>
public static T Get<T>( string key )
{
try
{
if ( ReflectionHelper.HttpContext.GetCurrentHttpContext() == null )
{
return ( T ) CallContext.LogicalGetData( key );
}
return ReflectionHelper.HttpContext.GetItemFromHttpContext<T>( key );
}
catch ( Exception ex )
{
Trace.WriteLine( string.Format( "An error occurred in ContextStorage.Get() retrieving key: {0} for type: {1}. Exception: {2}", key, typeof( T ), ex.Message ) );
}
return default( T );
}
/// <summary>
/// Stores an item.
/// </summary>
/// <param name="key">Item key</param>
/// <param name="obj">Object to store</param>
public static void Store( string key, object obj )
{
if ( ReflectionHelper.HttpContext.GetCurrentHttpContext() == null )
{
CallContext.LogicalSetData( key, obj );
}
else
{
ReflectionHelper.HttpContext.StoreItemInHttpContext( key, obj );
}
}
/// <summary>
/// Removes an item.
/// </summary>
/// <param name="key">Item key</param>
public static void Remove( string key )
{
if ( ReflectionHelper.HttpContext.GetCurrentHttpContext() == null )
{
CallContext.FreeNamedDataSlot( key );
}
else
{
ReflectionHelper.HttpContext.RemoveItemFromHttpContext( key );
}
}
}
public static class ReflectionHelper
{
/// <summary>
/// Provides access to System.Web.HttpContext.Current.Items via reflection.
/// </summary>
public static class HttpContext
{
/// <summary>
/// Attempts to load and cache System.Web.HttpContext.Current.Items.
/// </summary>
static HttpContext()
{
try
{
SystemDotWeb = Assembly
.Load( "System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" );
if ( SystemDotWeb == null ) return;
SystemDotWebDotHttpContext = SystemDotWeb.GetType( "System.Web.HttpContext", false, true );
if ( SystemDotWebDotHttpContext == null ) return;
// Get the current HTTP context property info
CurrentHttpContextPropertyInfo = SystemDotWebDotHttpContext
.GetProperty( "Current", ( BindingFlags.Public | BindingFlags.Static ) );
// Get the property info for the requested property
ItemsPropertyInfo = SystemDotWebDotHttpContext
.GetProperty( "Items", ( BindingFlags.Public | BindingFlags.Instance ) );
}
catch( Exception ex )
{
Trace.WriteLine( string.Format( "An error occurred attempting to get the current HttpContext. Exception: {0}", ex.Message ) );
}
}
public static readonly Assembly SystemDotWeb;
public static readonly Type SystemDotWebDotHttpContext;
public static readonly PropertyInfo CurrentHttpContextPropertyInfo;
public static readonly PropertyInfo ItemsPropertyInfo;
/// <summary>
/// Retrieves an item of type <typeparamref name="T"/> from the current HttpContext.
/// </summary>
/// <remarks>
/// This is functionally equivalent to:
/// T obj = ( T ) System.Web.HttpContext.Current.Items[ "SomeKeyName" ];
/// </remarks>
/// <typeparam name="T">Type requested</typeparam>
/// <param name="key">Key name</param>
/// <returns>Requested item</returns>
public static T GetItemFromHttpContext<T>( string key )
{
if ( SystemDotWeb != null && SystemDotWebDotHttpContext != null
&& CurrentHttpContextPropertyInfo != null && ItemsPropertyInfo != null )
{
// Get a reference to the current HTTP context
object currentHttpContext = CurrentHttpContextPropertyInfo.GetValue( null, null );
if ( currentHttpContext != null )
{
var items = ItemsPropertyInfo.GetValue( currentHttpContext, null ) as IDictionary;
if ( items != null )
{
object value = items[ key ];
if ( value != null )
{
return ( T ) value;
}
}
}
}
return default( T );
}
/// <summary>
/// Stores an item in the current HttpContext.
/// </summary>
/// <param name="key">Item key</param>
/// <param name="value">Item value</param>
public static void StoreItemInHttpContext( object key, object value )
{
object currentHttpContext = GetCurrentHttpContext();
if ( currentHttpContext != null )
{
var items = ItemsPropertyInfo.GetValue( currentHttpContext, null ) as IDictionary;
if ( items != null )
{
items.Add( key, value );
}
}
}
/// <summary>
/// Removes an item from the current HttpContext.
/// </summary>
/// <param name="key">Item key</param>
public static void RemoveItemFromHttpContext( object key )
{
object currentHttpContext = GetCurrentHttpContext();
if ( currentHttpContext != null )
{
var items = ItemsPropertyInfo.GetValue( currentHttpContext, null ) as IDictionary;
if ( items != null )
{
items.Remove( key );
}
}
}
/// <summary>
/// Gets the current HttpContext.
/// </summary>
/// <returns>Reference to the current HttpContext.</returns>
public static object GetCurrentHttpContext()
{
if ( SystemDotWeb != null && SystemDotWebDotHttpContext != null
&& CurrentHttpContextPropertyInfo != null && ItemsPropertyInfo != null )
{
// Get a reference to the current HTTP context
object currentHttpContext = CurrentHttpContextPropertyInfo.GetValue( null, null );
return currentHttpContext;
}
return null;
}
}
}
@csharpforevermore
Copy link

Nice code! I aspire to code things like that ReflectionHelper. Nice work mate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment