蛋疼的问题困扰我几天,于是下载了源码来看,终于成功,
以下示例以自己写的PreHttpRequestLifetimeManager,可能大部分人都用得到这个生命周期管理,
少费话,贴代码:
1、PreHttpRequestLifetimeManager
/// <summary>
/// 在HTTP请求生命周期内注入同一个实例
/// </summary>
public class PreHttpRequestLifetimeManager : LifetimeManager,IDisposable
{
/// <summary>
/// 键
/// </summary>
Guid _key;
/// <summary>
/// 值
/// </summary>
object _value;
/// <summary>
/// 在HTTP请求生命周期内注入同一个实例
/// </summary>
public PreHttpRequestLifetimeManager()
{
this._key = Guid.NewGuid();
}
/// <summary>
/// 缓存的注入实体
/// </summary>
IDictionary<Guid, object> ObjectDictionary
{
get
{
var objects = HttpContext.Current.Items[HttpModuleService.UnityObjects] as IDictionary<Guid, object>;
if (objects == null)
{
lock (this)
{
if (HttpContext.Current.Items[HttpModuleService.UnityObjects] == null)
{
objects = new Dictionary<Guid, object>();
HttpContext.Current.Items[HttpModuleService.UnityObjects] = objects;
}
else
{
return HttpContext.Current.Items[HttpModuleService.UnityObjects] as IDictionary<Guid, object>;
}
}
}
return objects;
}
}
public override object GetValue()
{
return this.ObjectDictionary.TryGetValue(this._key, out this._value) ? this._value : null;
}
public override void SetValue(object newValue)
{
if (this.ObjectDictionary.TryGetValue(this._key, out this._value)) return;
this._value = newValue;
this.ObjectDictionary.Add(this._key, this._value);
}
public override void RemoveValue()
{
if (this._value != null)
{
Dispose();
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (!disposing) return;
var objects = this.ObjectDictionary;
if (!objects.TryGetValue(this._key, out this._value)) return;
var disposable = this._value as IDisposable;
if (disposable != null)
{
objects.Remove(this._key);
}
_value = null;
}
}
/// <summary>
/// 自定义模块初始化
/// </summary>
public class HttpModuleService : IHttpModule
{
/// <summary>
/// DI生命周期对象标识
/// </summary>
internal const string UnityObjects = "UNITYOBJECTS";
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.EndRequest += this.OnUnityEndRequest;
}
/// <summary>
/// http请求结束时回收unity对象
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnUnityEndRequest(object sender, EventArgs e)
{
HttpContext.Current.Items.Remove(UnityObjects);
}
}
至于httpmodule怎么使用,网上找。
3、写个自定义容器
/// <summary>
/// 自定义容器
/// </summary>
public class DefaultLifetimeManagerExtension<TLifetimeManager> : UnityContainerExtension where TLifetimeManager : LifetimeManager, new()
{
/// <summary>
/// Install the default container behavior into the container.
/// </summary>
protected override void Initialize()
{
Context.Registering += OnRegister;
Context.RegisteringInstance += OnRegisterInstance;
Container.RegisterInstance(Container, new TLifetimeManager());
}
/// <summary>
/// Remove the default behavior from the container.
/// </summary>
public override void Remove()
{
Context.Registering -= OnRegister;
Context.RegisteringInstance -= OnRegisterInstance;
}
private void OnRegister(object sender, RegisterEventArgs e)
{
Context.RegisterNamedType(e.TypeFrom ?? e.TypeTo, e.Name);
if (e.TypeFrom != null)
{
if (e.TypeFrom.IsGenericTypeDefinition && e.TypeTo.IsGenericTypeDefinition)
{
Context.Policies.Set<IBuildKeyMappingPolicy>(
new GenericTypeBuildKeyMappingPolicy(new NamedTypeBuildKey(e.TypeTo, e.Name)),
new NamedTypeBuildKey(e.TypeFrom, e.Name));
}
else
{
Context.Policies.Set<IBuildKeyMappingPolicy>(
new BuildKeyMappingPolicy(new NamedTypeBuildKey(e.TypeTo, e.Name)),
new NamedTypeBuildKey(e.TypeFrom, e.Name));
}
}
if (e.LifetimeManager != null)
{
SetLifetimeManager(e.TypeTo, e.Name, e.LifetimeManager);
}
}
private void OnRegisterInstance(object sender, RegisterInstanceEventArgs e)
{
Context.RegisterNamedType(e.RegisteredType, e.Name);
SetLifetimeManager(e.RegisteredType, e.Name, e.LifetimeManager);
var identityKey = new NamedTypeBuildKey(e.RegisteredType, e.Name);
Context.Policies.Set<IBuildKeyMappingPolicy>(new BuildKeyMappingPolicy(identityKey), identityKey);
e.LifetimeManager.SetValue(e.Instance);
}
private void SetLifetimeManager(Type lifetimeType, string name, ILifetimePolicy lifetimeManager)
{
if ((lifetimeManager as TransientLifetimeManager) != null)
{
lifetimeManager = new TLifetimeManager();
}
if (lifetimeType.IsGenericTypeDefinition)
{
var factory =
new LifetimeManagerFactory(Context, lifetimeManager.GetType());
Context.Policies.Set<ILifetimeFactoryPolicy>(factory,
new NamedTypeBuildKey(lifetimeType, name));
}
else
{
Context.Policies.Set(lifetimeManager,
new NamedTypeBuildKey(lifetimeType, name));
if (lifetimeManager is IDisposable)
{
Context.Lifetime.Add(lifetimeManager);
}
}
}
}
最后一步,配置Global.asax实现注入:
private static UnityContainer container = new UnityContainer();
protected void Application_Start()
{
container.AddExtension(new DefaultLifetimeManagerExtension<PreHttpRequestLifetimeManager>());
}
我是用的mvc,经测试,在一个页面中调用不同控制器的 action,每个action都调用同一个接口注入过后获取的hashcode一致