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

Commit 6a79f5f

Browse files
author
Cao Trong Thang
committed
Support PerRequestLifetimeManager
1 parent b684c2a commit 6a79f5f

File tree

3 files changed

+143
-0
lines changed

3 files changed

+143
-0
lines changed

src/App_Start/UnityWebApiActivator.cs.pp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
var resolver = new UnityDependencyResolver(UnityConfig.Container);
2424

2525
GlobalConfiguration.Configuration.DependencyResolver = resolver;
26+
27+
// Uncomment if you want to use PerRequestLifetimeManager
28+
// Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
2629
}
2730

2831
/// <summary>

src/PerRequestLifetimeManager.cs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
using System;
2+
using Unity.Lifetime;
3+
4+
namespace Unity.AspNet.WebApi
5+
{
6+
public class PerRequestLifetimeManager : LifetimeManager,
7+
IInstanceLifetimeManager,
8+
IFactoryLifetimeManager,
9+
ITypeLifetimeManager
10+
{
11+
private readonly object _lifetimeKey = new object();
12+
13+
/// <summary>
14+
/// Retrieves a value from the backing store associated with this lifetime policy.
15+
/// </summary>
16+
/// <returns>The desired object, or null if no such object is currently stored.</returns>
17+
public override object GetValue(ILifetimeContainer container = null)
18+
{
19+
return UnityPerRequestHttpModule.GetValue(_lifetimeKey);
20+
}
21+
22+
/// <summary>
23+
/// Stores the given value into the backing store for retrieval later.
24+
/// </summary>
25+
/// <param name="newValue">The object being stored.</param>
26+
/// <param name="container"></param>
27+
public override void SetValue(object newValue, ILifetimeContainer container = null)
28+
{
29+
UnityPerRequestHttpModule.SetValue(_lifetimeKey, newValue);
30+
}
31+
32+
/// <summary>
33+
/// Removes the given object from the backing store.
34+
/// </summary>
35+
public override void RemoveValue(ILifetimeContainer container = null)
36+
{
37+
var disposable = GetValue() as IDisposable;
38+
39+
disposable?.Dispose();
40+
41+
UnityPerRequestHttpModule.SetValue(_lifetimeKey, null);
42+
}
43+
44+
/// <summary>
45+
/// Creates clone
46+
/// </summary>
47+
/// <returns></returns>
48+
protected override LifetimeManager OnCreateLifetimeManager()
49+
{
50+
return new PerRequestLifetimeManager();
51+
}
52+
}
53+
}

src/UnityPerRequestHttpModule.cs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Web;
5+
using Unity.Lifetime;
6+
7+
namespace Unity.AspNet.WebApi
8+
{
9+
public class UnityPerRequestHttpModule : IHttpModule
10+
{
11+
private static readonly object ModuleKey = new object();
12+
13+
internal static object GetValue(object lifetimeManagerKey)
14+
{
15+
var dict = GetDictionary(HttpContext.Current);
16+
17+
if (dict != null)
18+
{
19+
if (dict.TryGetValue(lifetimeManagerKey, out var obj))
20+
{
21+
return obj;
22+
}
23+
}
24+
25+
return LifetimeManager.NoValue;
26+
}
27+
28+
internal static void SetValue(object lifetimeManagerKey, object value)
29+
{
30+
var dict = GetDictionary(HttpContext.Current);
31+
32+
if (dict == null)
33+
{
34+
dict = new Dictionary<object, object>();
35+
36+
HttpContext.Current.Items[ModuleKey] = dict;
37+
}
38+
39+
dict[lifetimeManagerKey] = value;
40+
}
41+
42+
/// <summary>
43+
/// Disposes the resources used by this module.
44+
/// </summary>
45+
public void Dispose()
46+
{
47+
}
48+
49+
/// <summary>
50+
/// Initializes a module and prepares it to handle requests.
51+
/// </summary>
52+
/// <param name="context">An <see cref="HttpApplication"/> that provides access to the methods, properties,
53+
/// and events common to all application objects within an ASP.NET application.</param>
54+
public void Init(HttpApplication context)
55+
{
56+
(context ?? throw new ArgumentNullException(nameof(context))).EndRequest += OnEndRequest;
57+
}
58+
59+
private void OnEndRequest(object sender, EventArgs e)
60+
{
61+
var app = (HttpApplication)sender;
62+
63+
var dict = GetDictionary(app.Context);
64+
65+
if (dict != null)
66+
{
67+
foreach (var disposable in dict.Values.OfType<IDisposable>())
68+
{
69+
disposable.Dispose();
70+
}
71+
}
72+
}
73+
74+
private static Dictionary<object, object> GetDictionary(HttpContext context)
75+
{
76+
if (context == null)
77+
{
78+
throw new InvalidOperationException(
79+
"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.");
80+
}
81+
82+
var dict = (Dictionary<object, object>)context.Items[ModuleKey];
83+
84+
return dict;
85+
}
86+
}
87+
}

0 commit comments

Comments
 (0)