自定义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 Memberspublic void Dispose(){//clean-up code here.}public void Init(HttpApplication context){context.EndRequest += new EventHandler(context_EndRequest);}#endregionprivate 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中的配置文件內容如下,注意看紅色部分:<?xml version="1.0"?> <configuration><configSections><sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"><sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"><section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication" /><sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"><section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="Everywhere" /><section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication" /><section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication" /><section name="roleService" type="System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication" /></sectionGroup></sectionGroup></sectionGroup><section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" /></configSections><unity><typeAliases><typeAlias alias="string" type="System.String, mscorlib" /><typeAlias alias="singleton" type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager, Microsoft.Practices.Unity" /><typeAlias alias="transient" type="Microsoft.Practices.Unity.TransientLifetimeManager, Microsoft.Practices.Unity" /></typeAliases><containers> <container><types><type type="RequestLifeTimeManagerTest.Gateways.IProductGateway,RequestLifeTimeManagerTest" mapTo="RequestLifeTimeManagerTest.Gateways.ProductGateway, RequestLifeTimeManagerTest"></type></types><extensions><add type="RequestLifeTimeManagerTest.EFContainerExtension, RequestLifeTimeManagerTest" /></extensions></container></containers></unity><appSettings /><connectionStrings><add name="AdventureWorksLTEntities" connectionString="metadata=res://*/AdventureWorksModel.csdl|res://*/AdventureWorksModel.ssdl|res://*/AdventureWorksModel.msl;provider=System.Data.SqlClient;provider connection string="Data Source=GEFF-PC;Initial Catalog=AdventureWorksLT;Integrated Security=True;MultipleActiveResultSets=True"" providerName="System.Data.EntityClient" /></connectionStrings><system.web><!-- Set compilation debug="true" to insert debugging symbols into the compiled page. Because this affects performance, set this value to true only during development.--><compilation debug="true"><assemblies><add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" /><add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" /><add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /><add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" /><add assembly="System.Data.Entity, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /></assemblies></compilation><!--The <authentication> section enables configuration of the security authentication mode used by ASP.NET to identify an incoming user. --><authentication mode="Windows" /><!--The <customErrors> section enables configuration of what to do if/when an unhandled error occurs during the execution of a request. Specifically, it enables developers to configure html error pages to be displayed in place of a error stack trace.<customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm"><error statusCode="403" redirect="NoAccess.htm" /><error statusCode="404" redirect="FileNotFound.htm" /></customErrors>--><pages><controls><add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /><add tagPrefix="asp" namespace="System.Web.UI.WebControls" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /></controls></pages><httpHandlers><!--<remove verb="*" path="*.aspx"/><add verb="*" path="*.aspx" type="RequestLifeTimeManagerTest.UnityHttpHandlerFactory, RequestLifeTimeManagerTest"/>--><remove verb="*" path="*.asmx" /><add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /><add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /><add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" validate="false" /></httpHandlers><httpModules><add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /><add name="UnityModule" type="RequestLifeTimeManagerTest.UnityHttpModule,RequestLifeTimeManagerTest"/> </httpModules></system.web><system.codedom><compilers><compiler language="c#;cs;csharp" extension=".cs" warningLevel="4" type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"><providerOption name="CompilerVersion" value="v3.5" /><providerOption name="WarnAsError" value="false" /></compiler></compilers></system.codedom><!-- The system.webServer section is required for running ASP.NET AJAX under InternetInformation Services 7.0. It is not necessary for previous version of IIS.--><system.webServer><validation validateIntegratedModeConfiguration="false" /><modules><remove name="ScriptModule" /><add name="ScriptModule" preCondition="managedHandler" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /></modules><handlers><remove name="WebServiceHandlerFactory-Integrated" /><remove name="ScriptHandlerFactory" /><remove name="ScriptHandlerFactoryAppServices" /><remove name="ScriptResource" /><add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /><add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /><add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /></handlers></system.webServer><runtime><assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"><dependentAssembly><assemblyIdentity name="System.Web.Extensions" publicKeyToken="31bf3856ad364e35" /><bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0" /></dependentAssembly><dependentAssembly><assemblyIdentity name="System.Web.Extensions.Design" publicKeyToken="31bf3856ad364e35" /><bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0" /></dependentAssembly></assemblyBinding></runtime> </configuration>本文來自云棲社區合作伙伴“doNET跨平臺”,了解相關信息可以關注“opendotnet”微信公眾號
總結
以上是生活随笔為你收集整理的自定义Unity对象生命周期管理集成ADO.NET Entity Framework的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 万物互联时代 能效管理是怎样一个玩法?
- 下一篇: MongoDB干货篇之查询数据