1. 本文的实现类继承于IRepository
1 using System; 2 using System.Linq; 3 using System.Linq.Expressions; 4 using Zhang.Test.ELUnityUtility; 5 6 namespace Zhang.Test.IDataLayer 7 { 8 [UnityInjection("First", Name = "GenericRepository", ConfigFile = "Zhang.Test.exe.config")] 9 public interface IRepository 10 { 11 IQueryable<T> GetEntitiesByCondition<T>(Expression<Func<T, bool>> predicate = null) where T : class; 12 T GetEntityByCondition<T>(Expression<Func<T, bool>> predicate) where T : class; 13 T GetEntityByPK<T>(object key) where T : class; 14 IQueryable<T> GetEntitiesBySqlCommond<T>(String sqlCommond); 15 void Insert<T>(T entity) where T : class; 16 //void BatchInsert<T>(IEnumerable<T> entities); 17 void Update<T>(T entity) where T : class; 18 void Delete<T>(T entity) where T : class; 19 //void BatchDelete<T>(IEnumerable<T> entities); 20 int SaveChanges(); 21 } 22 }
2. 实现效果
通过调用接口的实现类可以实现调用其中的方法,如下:
class Repository:IRepository { public Insert<T>(T entity) where T: class { Console.WriteLine("Insert method"); } ........ }
3. 通过实例化Repository就可以调用其中的方法,但是AOP的作用是向在调用方法之前或之后注入其他代码,使它可以在不动Repository的基础上重用它。
4. 调用处理方法
我们先定义一段处理方法的代码,Unity规定它是ICallHandler的一个实现:
using System; using Microsoft.Practices.EnterpriseLibrary.Common.Configuration; using Microsoft.Practices.Unity; using Microsoft.Practices.Unity.InterceptionExtension; namespace Zhang.Test.DataLayer { [ConfigurationElementType(typeof (CustomCallHandlerData))] public class CallHandler : ICallHandler { #region ICallHandler 成员 public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) { if (input == null) throw new ArgumentNullException("input"); if (getNext == null) throw new ArgumentNullException("getNext"); //Console.WriteLine("begin...."); var result = getNext()(input, getNext); //Console.WriteLine("end...."); return result; } public int Order { get; set; } #endregion } }
5. OK, 下面我们怎么把CallHandler和IRepository关联起来,大体有两种方法:
- 通过代码直接关联,这种方法比较直接,首先,先建一个Attribute:
[AttributeUsage(AttributeTargets.Method)] public class CallHandlerAttribute : HandlerAttribute { public override ICallHandler CreateHandler(IUnityContainer container) { return new CallHandler(); } }
然后在IRepository的实现中使用如下代码:
[CallHandler]
class OutputImplement1 : IRepository
{
int SaveChanges()
}
这里靠此Attribute就将二者关联了起来
现在执行处写:
var container1 = new UnityContainer()
.AddNewExtension<Interception>()
.RegisterType<IOutput, OutputImplement1>();//声明UnityContainer并注册IOutput
container1
.Configure<Interception>()
.SetInterceptorFor<IOutput>(new InterfaceInterceptor());
var op1 = container1.Resolve<IOutput>();
op1.SaveChanges();//调用
- 用配置文件处理
如果用配置文件的话就不需要使用Attribute了,所以实现的类如下:
class OutputImplement2 : IRepository { int SaveChanges() }
这里我们不需要属性来标记了,而使用配置文件,我们建一个Unity.xml的配置文件,
<!--Unity configuration begin--> <unity xmlns="http://schemas.microsoft.com/practices/2010/unity"> <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration "> </sectionExtension> <!--<assembly name="Zhang.Test.DataLayer" /> <assembly name="Zhang.Test.IDataLayer" />--> <container name="First"> <extension type="Interception" /> <!--<register type="Zhang.Test.IDataLayer.ISample`1,Zhang.Test.IDataLayer" mapTo="Zhang.Test.DataLayer.SampleIocDAL,Zhang.Test.DataLayer" name="ISample"> <interceptor type="InterfaceInterceptor" /> <policyInjection /> </register>--> <register type="Zhang.Test.IDataLayer.IRepository,Zhang.Test.IDataLayer" mapTo="Zhang.Test.DataLayer.GenericRepository,Zhang.Test.DataLayer" name="GenericRepository"> </register> <!--<interceptors> <interceptor type="System.Data.Entity.Infrastructure.Interception.DatabaseLogger, EntityFramework"> <parameters> <parameter value="C:TempLogOutput.txt"/> </parameters> </interceptor> </interceptors>--> </container> </unity>
最后我们来执行一下,要比第一种复杂一点:
using System; using System.Linq; using System.Linq.Expressions; using Zhang.Test.ELUnityUtility; using Zhang.Test.IDataLayer; using Zhang.Test.Common; using System.Collections.Generic; using Zhang.Test.DataExchange; using Zhang.Test.DataTransferObject; namespace Zhang.Test.BusinessLayer { public class BaseBL { private readonly IRepository repository; public BaseBL() { string startTime = LoggerHelper.StartEvent("constructor"); try { //Initialize repository class by Unity repository = typeof (IRepository).Resolve<IRepository>() as IRepository; } catch (Exception e) { LoggerHelper.Error(e); throw e; } finally { LoggerHelper.EndEvent(startTime); } } public IQueryable<T> QueryEntitiesByCondition<T>(Expression<Func<T, bool>> predicate = null) where T : class { string startTime = LoggerHelper.StartEvent(); IQueryable<T> result = null; try { if (null != repository) { result = repository.GetEntitiesByCondition(predicate); } } catch (Exception e) { LoggerHelper.Error(e); throw; } finally { LoggerHelper.EndEvent(startTime); } return result; } /// <summary> /// Query first entity by filter /// </summary> /// <param name="predicate">Lamda expression</param> /// <returns>Entity</returns> public T QueryEntityByCondition<T>(Expression<Func<T, bool>> predicate) where T : class { string startTime = LoggerHelper.StartEvent(); T reslult = null; try { if (null != repository && null != predicate) { reslult = repository.GetEntityByCondition(predicate); } } catch (Exception e) // { LoggerHelper.Error(e); throw; } finally { LoggerHelper.EndEvent(startTime); } return reslult; } /// <summary> /// Query a entity by primary key /// </summary> /// <param name="key">primary key of entity</param> /// <returns>Entity</returns> public T QueryEntityByPK<T>(object key) where T : class { string startTime = LoggerHelper.StartEvent(); T reslult = null; try { if (null != repository && null != key) { reslult = repository.GetEntityByPK<T>(key); } } catch (Exception e) { LoggerHelper.Error(e); throw; } finally { LoggerHelper.EndEvent(startTime); } return reslult; } /// <summary> /// Query entity set by sqlcommond, property of entity should be match with sqlcommond /// </summary> /// <param name="sqlCommond">SQL</param> /// <returns>Entity set</returns> public IQueryable<T> QueryEntitiesBySqlCommond<T>(String sqlCommond) { string startTime = LoggerHelper.StartEvent(); IQueryable<T> result = null; try { Dictionary<string, Object> msg = new Dictionary<string, object>(); msg.Add("QueryEntitiesBySqlCommond", sqlCommond); LoggerHelper.Info(msg); if (null != repository && !string.IsNullOrEmpty(sqlCommond)) { result = repository.GetEntitiesBySqlCommond<T>(sqlCommond); } } catch (Exception e) { LoggerHelper.Error(e); throw; } finally { LoggerHelper.EndEvent(startTime); } return result; } /// <summary> /// Query entity set by sqlcommond, property of entity should be match with sqlcommond /// </summary> /// <param name="sqlCommond">SQL</param> /// <returns>Entity set</returns> public string QueryValueBySqlCommond(String sqlCommond) { string startTime = LoggerHelper.StartEvent(); //IQueryable<string> result = null; try { Dictionary<string, Object> msg = new Dictionary<string, object>(); msg.Add("QueryValueBySqlCommond", sqlCommond); LoggerHelper.Info(msg); if (null != repository && !string.IsNullOrEmpty(sqlCommond)) { return QueryEntitiesBySqlCommond<string>(sqlCommond).FirstOrDefault(); /*result = QueryEntitiesBySqlCommond<string>(sqlCommond); if (result != null && result.ToList().Count > 0) { return result.ToList()[0]; }*/ } } catch (Exception e) { LoggerHelper.Error(e); throw; } finally { LoggerHelper.EndEvent(startTime); } return ""; } /// <summary> /// Query by sqlcommond, property of entity should be match with sqlcommond /// </summary> /// <param name="sqlCommond">SQL</param> /// <returns>num</returns> public int QueryIntValueBySqlCommond(String sqlCommond) { string startTime = LoggerHelper.StartEvent(); //IQueryable<int?> result = null; try { Dictionary<string, Object> msg = new Dictionary<string, object>(); msg.Add("QueryIntValueBySqlCommond", sqlCommond); LoggerHelper.Info(msg); if (null != repository && !string.IsNullOrEmpty(sqlCommond)) { int? result = QueryEntitiesBySqlCommond<int?>(sqlCommond).FirstOrDefault(); if (result != null) { return Convert.ToInt32(result); } } } catch (Exception e) { LoggerHelper.Error(e); throw; } finally { LoggerHelper.EndEvent(startTime); } return -1; } /// <summary> /// Create entity /// </summary> /// <param name="entity">entity</param> public void CreateEntity<T>(T entity) where T : class { string startTime = LoggerHelper.StartEvent(); try { if (null != repository && null != entity) { repository.Insert(entity); } } catch (Exception e) { LoggerHelper.Error(e); throw; } finally { LoggerHelper.EndEvent(startTime); } } /// <summary> /// Modify entity /// </summary> /// <param name="entity">entity</param> public void ModifyEntity<T>(T entity) where T : class { string startTime = LoggerHelper.StartEvent(); try { if (null != repository && null != entity) { repository.Update(entity); } } catch (Exception e) { LoggerHelper.Error(e); throw; } finally { LoggerHelper.EndEvent(startTime); } } /// <summary> /// Remove entity /// </summary> /// <param name="entity">entity</param> public void RemoveEntity<T>(T entity) where T : class { string startTime = LoggerHelper.StartEvent(); try { if (null != repository && null != entity) { repository.Delete(entity); } } catch (Exception e) { LoggerHelper.Error(e); throw; } finally { LoggerHelper.EndEvent(startTime); } } /// <summary> /// commit transaction /// </summary> /// <returns>Number of objects to be saved</returns> public int SaveChanges() { string startTime = LoggerHelper.StartEvent(); var nums = 0; try { if (null != repository) { nums = repository.SaveChanges(); } } catch (Exception e) { LoggerHelper.Error(e); throw; } finally { LoggerHelper.EndEvent(startTime); } return nums; } public string ImportSuccess() { return ResourceHelper.GetRsByKey("Common_Result_ImprotEntitySuccessfully"); } public string ImportUnSuccess() { return ResourceHelper.GetRsByKey("Common_Result_ImprotEntityUnsuccessfully"); } public ExecutionResult CreateExecutionResult(string rowIndex,string message) { ExecutionResult er = new ExecutionResult(); er.RowIndex = rowIndex; er.Message = message; return er; } } }
附加Unity的代码:
1. using System; using System.Collections.Generic; using Microsoft.Practices.EnterpriseLibrary.PolicyInjection; using Microsoft.Practices.Unity; using Microsoft.Practices.Unity.Configuration; namespace Zhang.Test.ELUnityUtility { public static class ELUnityUtility { public static T Resolve<T>() where T : class { return Resolve<T>(typeof (T)) as T; } public static object Resolve<T>(this Type type) { var attrs = type.GetCustomAttributes(typeof (UnityInjectionAttribute), true) as UnityInjectionAttribute[]; if (attrs != null && attrs.Length > 0) { var attr = attrs[0]; var unitySection = attr.GetUnityConfigurationSection(); if (unitySection != null) { var container = new UnityContainer().LoadConfiguration(unitySection, string.IsNullOrEmpty(attr.Container) ? unitySection.Containers.Default.Name : attr.Container); var obj = string.IsNullOrEmpty(attr.Name) ? container.Resolve(type) : container.Resolve(type, attr.Name); if (obj != null) { var piabAtttr = obj.GetType().GetCustomAttributes(typeof (ELPolicyinjectionAttribute), false) as ELPolicyinjectionAttribute[]; if (piabAtttr.Length > 0) { obj = PolicyInjection.Wrap(type, obj); } return obj; } } } return null; } public static IEnumerable<T> ResolveAll<T>() where T : class { return ResolveAll(typeof (T)) as IEnumerable<T>; } public static object ResolveAll(this Type type) { var attrs = type.GetCustomAttributes(typeof (UnityInjectionAttribute), true) as UnityInjectionAttribute[]; if (attrs != null && attrs.Length > 0) { var attr = attrs[0]; var unitySection = attr.GetUnityConfigurationSection(); if (unitySection != null) { var container = new UnityContainer().LoadConfiguration(unitySection, string.IsNullOrEmpty(attr.Container) ? unitySection.Containers.Default.Name : attr.Container); return container.ResolveAll(type); } } return null; } } } 2. using System; using System.Configuration; using System.IO; using Microsoft.Practices.Unity.Configuration; namespace Zhang.Test.ELUnityUtility { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)] public class UnityInjectionAttribute : Attribute { public UnityInjectionAttribute(string Container) { this.Container = Container; } public string Container { get; set; } public string ConfigFile { get; set; } public string Name { get; set; } public UnityConfigurationSection GetUnityConfigurationSection() { if (!string.IsNullOrEmpty(ConfigFile)) { var fileMap = new ExeConfigurationFileMap { ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ConfigFile) }; var configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None); return configuration == null ? null : configuration.GetSection(UnityConfigurationSection.SectionName) as UnityConfigurationSection; } return ConfigurationManager.GetSection(UnityConfigurationSection.SectionName) as UnityConfigurationSection; } } [AttributeUsage(AttributeTargets.Class)] public class ELPolicyinjectionAttribute : Attribute { public string Name { get; set; } } }