自定义Unity对象生命周期管理集成ADO.NET Entity Framework

在Unity中,从Unity 取得的实例为 Transient。如果你希望使用多线程方式,就需要在组成时使用lifecycle参数,这时候取出的组件就不再是同一个了。在Unity IOC中,它支持我们对于组件的实例进行控制,也就是说我们可以透明的管理一个组件拥有多少个实例。Unity IOC容器提供了如下几种生命处理方式:
# Singleton:一个组件只有一个实例被创建,所有请求的客户使用程序得到的都是同一个实例。
# Transient:这种处理方式与我们平时使用new的效果是一样的,对于每次的请求得到的都是一个新的实例。
# Custom:自定义的生命处理方式。

我 要增加一个Request的,一个Request请求一个实例,然后在Request结束的时候,回收资源。 增加一个Resquest级别的LifetimeManager,HttpContext.Items中数据是Request期间共享数据用的,所以 HttpContext.Items中放一个字典,用类型为key,类型的实例为value。如果当前Context.Items中有类型的实例,就直接 返回实例。 ObjectContext本身是有缓存的,整个Request内都是一个ObjectContext,ObjectContext一级缓存能力进一步利 用。

用在Unity中,如何获取对象的实例及如何销毁对象都是由LifetimeManager完成的,其定义如下
public abstract class LifetimeManager : ILifetimePolicy, IBuilderPolicy
{
protected LifetimeManager();

public abstract object GetValue();
public abstract void RemoveValue();
public abstract void SetValue(object newValue);
}

其中GetValue方法获取对象实例,RemoveValue方法销毁对象,SetValue方法为对外引用的保存提供新的实例

有了这3个方法,就可以通过自定义LifetimeManager来实现从HttpContext中取值。

下面我们来实现Unity集成ADO.NET Entity Framework的工作:

1、利用Unity的依赖注入,ObjectContext会给我们生成3个构造函数,类似于下面的代码:

// Original file name:
// Generation date: 2008/8/24 10:05:33
namespace RequestLifeTimeManagerTest
{
using Microsoft.Practices.Unity;

/// <summary>
/// There are no comments for AdventureWorksLTEntities in the schema.
/// </summary>
public partial class AdventureWorksLTEntities : global::System.Data.Objects.ObjectContext
{
/// <summary>
/// Initializes a new AdventureWorksLTEntities object using the connection string found in the 'AdventureWorksLTEntities' section of the application configuration file.
/// </summary>
public AdventureWorksLTEntities() :
base("name=AdventureWorksLTEntities", "AdventureWorksLTEntities")
{
this.OnContextCreated();
}
/// <summary>
/// Initialize a new AdventureWorksLTEntities object.
/// </summary>
public AdventureWorksLTEntities(string connectionString) :
base(connectionString, "AdventureWorksLTEntities")
{
this.OnContextCreated();
}
/// <summary>
/// Initialize a new AdventureWorksLTEntities object.
/// </summary>
public AdventureWorksLTEntities(global::System.Data.EntityClient.EntityConnection connection) :
base(connection, "AdventureWorksLTEntities")
{
this.OnContextCreated();
}
partial void OnContextCreated();

……

}

构造函数注入包含了二种情况,一种是类仅有一个构造函数时,Unity 可以进行自动注入;另一种情况是,类包含多个构造函数时,必须使用 Attribute 或者配置文件指定注入时使用的构造函数。

ObjectContext有多个构造函数,而且ObjectContext的构造函数代码是Visual Studio 代码生成的,最好的选择是使用配置文件或者使用配置API指定注入时使用的构造函数。下面是使用配置API:

namespace RequestLifeTimeManagerTest
{
public class EFContainerExtension : UnityContainerExtension
{
protected override void Initialize()
{
this.Container.RegisterType<AdventureWorksLTEntities, AdventureWorksLTEntities>(new RequestControlledLifetimeManager(typeof(AdventureWorksLTEntities)))
.Configure<InjectedMembers>()
.ConfigureInjectionFor<AdventureWorksLTEntities>(new InjectionConstructor());
}
}
}

我们定义了一个Unity扩展,在扩展类EFContainerExtension 我们选择了第一个构造函数以及ObjectContext使用RequestControlledLifetimeManager实现ObjectContext的生命周期管理。
2、实现RequestControlledLifetimeManager,完成对整个Request内都是一个ObjectContext的对象的生命周期管理:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.Practices.Unity;


namespace RequestLifeTimeManagerTest
{
public class RequestControlledLifetimeManager : LifetimeManager
{
private Type objectType;

/// <summary>
///
/// </summary>
/// <param name="t"></param>
public RequestControlledLifetimeManager(Type t)
{
this.objectType = t;
}

private IDictionary<Type, object> GetObjectTable()
{
IDictionary<Type, object> objects = HttpContext.Current.Items[RequestLifeTimeManagerTest.UnityHttpModule.UNITYOBJECTS]

as IDictionary<Type, object>;

if (objects == null)
{
lock (this)
{
if (HttpContext.Current.Items[RequestLifeTimeManagerTest.UnityHttpModule.UNITYOBJECTS] == null)
{
objects = new Dictionary<Type, object>();
HttpContext.Current.Items[RequestLifeTimeManagerTest.UnityHttpModule.UNITYOBJECTS] = objects;
}
else
{
return HttpContext.Current.Items[RequestLifeTimeManagerTest.UnityHttpModule.UNITYOBJECTS]
as IDictionary<Type, object>;
}
}
}
return objects;
}

public override object GetValue()
{
IDictionary<Type, object> objects = this.GetObjectTable();
object obj = null;
if (objects.TryGetValue(this.objectType, out obj))
{
return obj;
}
return null;
}

public override void RemoveValue()
{
IDictionary<Type, object> objects = this.GetObjectTable();
object obj = null;
if (objects.TryGetValue(this.objectType, out obj))
{
((IDisposable)obj).Dispose();
objects.Remove(this.objectType);
}
}

public override void SetValue(object newValue)
{
IDictionary<Type, object> objects = this.GetObjectTable();
objects.Add(this.objectType, newValue);
}
}
}

写一个HttpMoudle,在Request结束的时候回收资源。



using System;
using System.Web;
using System.Collections.Generic;



namespace RequestLifeTimeManagerTest
{
public class UnityHttpModule : IHttpModule
{
internal const string UNITYOBJECTS = "UNITYOBJECTS";
#region IHttpModule Members

public void Dispose()
{
//clean-up code here.
}

public void Init(HttpApplication context)
{
context.EndRequest += new EventHandler(context_EndRequest);

}

#endregion

private void context_EndRequest(object sender, EventArgs e)
{
IDictionary<Type, object> objects = HttpContext.Current.Items[UNITYOBJECTS]
as IDictionary<Type, object>;
if (objects != null)
{
foreach (Type key in objects.Keys)
{
if (objects[key] is IDisposable)
{
((IDisposable)objects[key]).Dispose();
}
}
HttpContext.Current.Items.Remove(UNITYOBJECTS);
}
}

}
}

3、web.config中的配置文件内容如下,注意看红色部分:

Code

posted on 2008-12-04 09:54  执法长老  阅读(610)  评论(0编辑  收藏  举报

导航