WebApi Unity PerRequestLifetimeManagert.md

在WebApi 中自定义 Unity PerRequestLifetimeManagert

实现思路

  1. 使用HttpContextItems 属性作为实例对象容器
  2. 自定义UnityPerRequestHttpModule继承IHttpModule管理实例对象容器,在HttpApplicationEndRequest事件触发时,销毁容器中该请求的实例对象。
  3. 自定义PerRequestLifetimeManager继承LifetimeManager,调用UnityPerRequestHttpModule获取或设置实例对象。

自定义UnityPerRequestHttpModule

/// <summary>
/// Unity PerRequest 生命周期HttpModule
/// Unity 产生的对象在 HttpModule 生命周期中有效
/// 在HttpModule生命周期中每个对象只产生一次
/// </summary>
public class UnityPerRequestHttpModule : IHttpModule
{
    internal static readonly object ModuleKey = new object();
    HttpApplication Context;
    /// <summary>
    /// 释放
    /// </summary>
    public void Dispose()
    {
        LoggerService.LoggerService.ApplicationLogger.Debug($"UnityPerRequestHttpModule【{Context.Request.Url}】销毁");
    }
    /// <summary>
    /// 初始化
    /// </summary>
    /// <param name="context">HTTPApplication上下文</param>
    public void Init(HttpApplication context)
    {
        Context = context;
        context.EndRequest += Context_EndRequest;
    }

    /// <summary>
    /// 释放 System.Web.IHttpModule 接口和 System.Web.IHttpHandler 接口之间组织和共享的该HttpModel数据
    /// </summary>
    /// <param name="sender">HttpApplication</param>
    /// <param name="e"></param>
    private void Context_EndRequest(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();
            }
        }
    }
    /// <summary>
    /// 在System.Web.IHttpModule 接口和 System.Web.IHttpHandler 接口之间组织和共享的数据中获取该HttpModel的数据
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>
    private static Dictionary<object, object> GetDictionary(HttpContext context)
    {
        if (context == null)
            throw new ArgumentNullException("context");

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

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

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

        return dict;
    }

    /// <summary>
    /// 准备模块和注册器
    /// </summary>
    internal static void Register()
    {
        DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
    }

    /// <summary>
    /// 从 HttpModel的数据中获取指定对象 
    /// </summary>
    /// <param name="lifetimeManagerKey">指定对象的Key</param>
    /// <returns></returns>
    internal static object GetValue(object lifetimeManagerKey)
    {
        var dict = GetDictionary(HttpContext.Current);

        object obj = null;

        if (dict.TryGetValue(lifetimeManagerKey, out obj))
        {
            return obj;
        }

        return null;
    }
    /// <summary>
    /// 将对象和对象对应的Key存入HttpModel的数据中
    /// </summary>
    /// <param name="lifetimeManagerKey">指定对象的Key</param>
    /// <param name="value">指定对象</param>
    internal static void SetValue(object lifetimeManagerKey, object value)
    {
        GetDictionary(HttpContext.Current)[lifetimeManagerKey] = value;
    }
}

在WebCinfig中配置自定义的UnityPerRequestHttpModule

<system.web>
    <httpModules>
        <add name="UnityPerRequestHttpModule" type="UnityPerRequestHttpModule"/>
    </httpModules>
</system.web>
<system.webServer>
    <modules>
        <remove name="UnityPerRequestHttpModule" />
        <add name="UnityPerRequestHttpModule" type="UnityPerRequestHttpModule"  />
    </modules>
</system.webServer>

自定义PerRequestLifetimeManager

/// <summary>
/// WebAPI 请求生命周期
/// 实际是HttpModule生命周期
/// 在HttpModule生命周期中每个对象只产生一次
/// </summary>
public class PerRequestLifetimeManager : LifetimeManager
{
    private Type instanceType;
    /// <summary>
    /// 实例化WebAPI 请求生命周期
    /// </summary>
    public PerRequestLifetimeManager() { }
    /// <summary>
    /// 实例化WebAPI 请求生命周期
    /// </summary>
    /// <param name="instanceType">
    /// 实例类型
    /// 设置该参数后在一个HttpModel生命周期中对象不同接口解析到的是同一个实例
    /// </param>
    public PerRequestLifetimeManager(Type instanceType)
    {
        this.instanceType = instanceType;
    }
    private readonly object lifetimeKey = Guid.NewGuid();
    /// <summary>
    /// 生命周期Key
    /// </summary>
    public object LifetimeKey => instanceType == null ? lifetimeKey : instanceType.FullName;

    /// <summary>
    /// 获取对象
    /// </summary>
    /// <param name="container">生命周期容器</param>
    /// <returns></returns>
    public override object GetValue(ILifetimeContainer container = null)
    {
        LoggerService.LoggerService.ApplicationLogger.Debug($"从Request生命周期获取实例【{LifetimeKey}】");
        return UnityPerRequestHttpModule.GetValue(LifetimeKey);
    }
    /// <summary>
    /// 删除对象
    /// </summary>
    /// <param name="container">生命周期容器</param>
    public override void RemoveValue(ILifetimeContainer container = null)
    {
        var disposable = this.GetValue() as IDisposable;

        if (disposable != null)
        {
            disposable.Dispose();
        }

        LoggerService.LoggerService.ApplicationLogger.Debug($"从Request生命周期删除实例【{LifetimeKey}】");
        UnityPerRequestHttpModule.SetValue(LifetimeKey, null);
    }
    /// <summary>
    /// 设置对象
    /// </summary>
    /// <param name="newValue">实例化的对象</param>
    /// <param name="container">生命周期容器</param>
    public override void SetValue(object newValue, ILifetimeContainer container = null)
    {
        LoggerService.LoggerService.ApplicationLogger.Debug($"向Request生命周期添加实例【{LifetimeKey}】");
        UnityPerRequestHttpModule.SetValue(LifetimeKey, newValue);
    }
    /// <summary>
    /// 创建生命周期管理器时调用
    /// </summary>
    /// <returns></returns>
    protected override LifetimeManager OnCreateLifetimeManager()
    {
        return this;
    }
}

使用方法

var container = new UnityContainer();

//注册对象映射
container.RegisterType<ITestA, TestA>(new PerRequestLifetimeManager(typeof(TestA)));
container.RegisterType<ITestB, TestB>(new PerRequestLifetimeManager());

//解析对象
var testA = container.Resolve<ITestA>();
var testB = container.Resolve<ITestB>();
posted @ 2020-12-14 17:10  $("#阿飞")  阅读(146)  评论(0编辑  收藏  举报