Skip to content
This repository has been archived by the owner on Mar 2, 2023. It is now read-only.

Support PerRequestLifetimeManager #20

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/App_Start/UnityWebApiActivator.cs.pp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
var resolver = new UnityDependencyResolver(UnityConfig.Container);

GlobalConfiguration.Configuration.DependencyResolver = resolver;

// Uncomment if you want to use PerRequestLifetimeManager
// Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
}

/// <summary>
Expand Down
53 changes: 53 additions & 0 deletions src/PerRequestLifetimeManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System;
using Unity.Lifetime;

namespace Unity.AspNet.WebApi
{
public class PerRequestLifetimeManager : LifetimeManager,
IInstanceLifetimeManager,
IFactoryLifetimeManager,
ITypeLifetimeManager
{
private readonly object _lifetimeKey = new object();

/// <summary>
/// Retrieves a value from the backing store associated with this lifetime policy.
/// </summary>
/// <returns>The desired object, or null if no such object is currently stored.</returns>
public override object GetValue(ILifetimeContainer container = null)
{
return UnityPerRequestHttpModule.GetValue(_lifetimeKey);
}

/// <summary>
/// Stores the given value into the backing store for retrieval later.
/// </summary>
/// <param name="newValue">The object being stored.</param>
/// <param name="container"></param>
public override void SetValue(object newValue, ILifetimeContainer container = null)
{
UnityPerRequestHttpModule.SetValue(_lifetimeKey, newValue);
}

/// <summary>
/// Removes the given object from the backing store.
/// </summary>
public override void RemoveValue(ILifetimeContainer container = null)
{
var disposable = GetValue() as IDisposable;

disposable?.Dispose();

UnityPerRequestHttpModule.SetValue(_lifetimeKey, null);
}

/// <summary>
/// Creates clone
/// </summary>
/// <returns></returns>
protected override LifetimeManager OnCreateLifetimeManager()
{
return new PerRequestLifetimeManager();
}
}
}
87 changes: 87 additions & 0 deletions src/UnityPerRequestHttpModule.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Unity.Lifetime;

namespace Unity.AspNet.WebApi
{
public class UnityPerRequestHttpModule : IHttpModule
{
private static readonly object ModuleKey = new object();

internal static object GetValue(object lifetimeManagerKey)
{
var dict = GetDictionary(HttpContext.Current);

if (dict != null)
{
if (dict.TryGetValue(lifetimeManagerKey, out var obj))
{
return obj;
}
}

return LifetimeManager.NoValue;
}

internal static void SetValue(object lifetimeManagerKey, object value)
{
var dict = GetDictionary(HttpContext.Current);

if (dict == null)
{
dict = new Dictionary<object, object>();

HttpContext.Current.Items[ModuleKey] = dict;
}

dict[lifetimeManagerKey] = value;
}

/// <summary>
/// Disposes the resources used by this module.
/// </summary>
public void Dispose()
{
}

/// <summary>
/// Initializes a module and prepares it to handle requests.
/// </summary>
/// <param name="context">An <see cref="HttpApplication"/> that provides access to the methods, properties,
/// and events common to all application objects within an ASP.NET application.</param>
public void Init(HttpApplication context)
{
(context ?? throw new ArgumentNullException(nameof(context))).EndRequest += OnEndRequest;
}

private void OnEndRequest(object sender, EventArgs e)
{
var app = (HttpApplication)sender;

var dict = GetDictionary(app.Context);

if (dict != null)
{
foreach (var disposable in dict.Values.OfType<IDisposable>())
{
disposable.Dispose();
}
}
}

private static Dictionary<object, object> GetDictionary(HttpContext context)
{
if (context == null)
{
throw new InvalidOperationException(
"The PerRequestLifetimeManager can only be used in the context of an HTTP request.Possible causes for this error are using the lifetime manager on a non-ASP.NET application, or using it in a thread that is not associated with the appropriate synchronization context.");
}

var dict = (Dictionary<object, object>)context.Items[ModuleKey];

return dict;
}
}
}