zoukankan      html  css  js  c++  java
  • IOC之Unity的使用详解

    原文链接:https://www.cnblogs.com/hua66/p/9670639.html

     Unity作为Microsoft推出IOC容器,其功能是非常丰富的,其中需要注意的地方也不少。以下是个人在项目中使用Unity的场景并附实例。

    一、封装数据访问层

      1、定义对象与DB交互接口  

     1 public interface IBaseService : IDisposable
     2     {
     3         T FindEntity<T>(int id) where T : class;
     4         void AddEntity<T>(T entity) where T : class;
     5         Task<int> AddEntities<T>(IEnumerable<T> entities) where T : class;
     6         void UpdateEntity<T>(T entity) where T : class;        
     7         Task<int> UpdateEntities<T>(IEnumerable<T> entities) where T : class;
     8         void DeleteEntity<T>(int id) where T : class;
     9         void DeleteEntity<T>(T entity) where T : class;
    10         Task<int> DeleteEntities<T>(IEnumerable<T> entities) where T : class;
    11         Task<int> DeleteEntities<T>(Func<T, bool> whereLambda) where T : class;
    12         IQueryable<T> LoadEntities<T>() where T : class;
    13         IQueryable<T> LoadEntities<T>(Func<T, bool> whereLambda) where T : class;
    14         IQueryable<T> LoadEntities<T>(Func<T, bool> whereLambda, int pageSize, int pageIndex, out int count) where T : class;
    15         IQueryable<T> ExcuteQuery<T>(string sql, SqlParameter[] parameters) where T : class;
    16         void Excute<T>(string sql, SqlParameter[] parameters) where T : class;
    17         int Commit();
    18         Task<int> CommitAsync();
    19 
    20     }
    View Code

      2、用EF实现数据访问层接口  

      1 public abstract class EntityService : IBaseService
      2     {
      3         protected DbContext DBContext { get; private set; }
      4         public EntityService(DbContext dbContext)
      5         {
      6             this.DBContext = dbContext;
      7         }
      8         public T FindEntity<T>(int id) where T : class
      9         {
     10             T entity = this.DBContext.Set<T>().Find(id);
     11             return entity;
     12         }
     13         public void AddEntity<T>(T entity) where T : class
     14         {
     15             this.DBContext.Entry(entity).State = EntityState.Added;
     16         }
     17 
     18         [Obsolete("不建议使用基于EF实现批量操作函数,此操作已异步提交!", false)]
     19         public Task<int> AddEntities<T>(IEnumerable<T> entities) where T : class
     20         {
     21             this.DBContext.Set<T>().AddRange(entities);
     22             return this.CommitAsync();
     23         }
     24         public void UpdateEntity<T>(T entity) where T : class
     25         {
     26             this.DBContext.Entry(entity).State = EntityState.Modified;
     27             //this.DBContext.Set<T>().Attach(entity);            
     28             //this.DBContext.Entry(entity).Property("")
     29         }
     30 
     31         [Obsolete("不建议使用基于EF实现批量操作函数,此操作已异步提交!", false)]
     32         public Task<int> UpdateEntities<T>(IEnumerable<T> entities) where T : class
     33         {
     34             this.DBContext.Configuration.AutoDetectChangesEnabled = false;
     35             foreach (var entity in entities)
     36             {
     37                 this.DBContext.Entry(entity).State = EntityState.Modified;
     38             }
     39             this.DBContext.Configuration.AutoDetectChangesEnabled = true;
     40             //this.DBContext.Entry(entities).State= EntityState.Modified;
     41             return this.CommitAsync();
     42         }
     43         public void DeleteEntity<T>(int id) where T : class
     44         {
     45 
     46             T entity = this.DBContext.Set<T>().Find(id);
     47             this.DBContext.Set<T>().Remove(entity);
     48         }
     49         public void DeleteEntity<T>(T entity) where T : class
     50         {
     51             this.DBContext.Set<T>().Attach(entity);
     52             this.DBContext.Entry(entity).State = EntityState.Deleted;
     53         }
     54 
     55         [Obsolete("不建议使用基于EF实现批量操作函数,此操作已异步提交!", false)]
     56         public Task<int> DeleteEntities<T>(IEnumerable<T> entities) where T : class
     57         {            
     58             //this.DBContext.Configuration.AutoDetectChangesEnabled = false;
     59             //foreach (var entity in entities)
     60             //{
     61             //    this.DBContext.Entry(entity).State = EntityState.Deleted;
     62             //}            
     63             //this.DBContext.Configuration.AutoDetectChangesEnabled = true;
     64             this.DBContext.Set<T>().RemoveRange(entities);
     65             return this.CommitAsync();
     66         }
     67 
     68         [Obsolete("不建议使用基于EF实现批量操作函数,此操作已异步提交!", false)]
     69         public Task<int> DeleteEntities<T>(Func<T, bool> whereLambda) where T : class
     70         {
     71             IQueryable<T> entities = this.DBContext.Set<T>().Where(whereLambda).AsQueryable();
     72             //this.DBContext.Entry(entities).State = EntityState.Deleted;
     73             this.DBContext.Set<T>().RemoveRange(entities);
     74             return this.CommitAsync();
     75         }
     76         public IQueryable<T> LoadEntities<T>() where T : class
     77         {
     78             return this.DBContext.Set<T>();
     79         }
     80         public IQueryable<T> LoadEntities<T>(Func<T, bool> whereLambda) where T : class
     81         {
     82             return this.DBContext.Set<T>().Where<T>(whereLambda).AsQueryable();
     83         }
     84         public IQueryable<T> LoadEntities<T>(Func<T, bool> whereLambda, int pageSize, int pageIndex, out int count) where T : class
     85         {
     86             count = 0;
     87             count = this.DBContext.Set<T>().Where(whereLambda).AsQueryable().Count();
     88             //return this.DBContext.Set<T>().Where<T>(whereLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsQueryable();
     89             return this.DBContext.Set<T>().Where(whereLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsQueryable();
     90         }
     91 
     92         #region
     93         public virtual int Commit()
     94         {
     95             return this.DBContext.SaveChanges();
     96         }
     97         public virtual Task<int> CommitAsync()
     98         {
     99             return this.DBContext.SaveChangesAsync();
    100         }
    101         #endregion
    102         public virtual void Dispose()
    103         {
    104             if (this.DBContext!=null)
    105             {
    106                 this.DBContext.Dispose();
    107             }            
    108         }
    109 
    110         public IQueryable<T> ExcuteQuery<T>(string sql, SqlParameter[] parameters) where T : class
    111         {
    112             return this.DBContext.Database.SqlQuery<T>(sql, parameters).AsQueryable();
    113         }
    114 
    115         public void Excute<T>(string sql, SqlParameter[] parameters) where T : class
    116         {
    117             DbContextTransaction trans = null;
    118             try
    119             {
    120                 trans = this.DBContext.Database.BeginTransaction();
    121                 this.DBContext.Database.ExecuteSqlCommand(sql, parameters);
    122                 trans.Commit();
    123             }
    124             catch (Exception ex)
    125             {
    126                 if (trans != null)
    127                     trans.Rollback();
    128                 throw ex;
    129             }
    130         }
    131     }
    View Code

    二、封装Unity容器对象  

     1  public class ContainerFactory
     2     {
     3         private static IUnityContainer _iUnityContainer = null;
     4         private ContainerFactory()
     5         {
     6 
     7         }
     8         static ContainerFactory()
     9         {
    10             ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
    11             fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "CfgFiles\Unity.Config.xml");//找配置文件的路径
    12             Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
    13             UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
    14 
    15             _iUnityContainer = new UnityContainer();
    16             section.Configure(_iUnityContainer, "TestContainer");
    17         }
    18 
    19         public static IUnityContainer GetContainerInstance()
    20         {
    21             return _iUnityContainer;
    22         }
    23     }
    View Code

      上面使用静态对象方式读取Unity的配置文件并返回Unity的容器对象,方便其他对象使用。

    三、示例

      1、用Code First初始化DB

        1.1、Models    

     1 [TableAttribute("Base_Sys_User")]
     2     public class User
     3     {
     4         [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
     5         public int ID { get; set; }
     6 
     7         [Column("Account")]
     8         [StringLength(50)]
     9         public String Code { get; set; }
    10 
    11         [StringLength(20)]
    12         public String Name { get; set; }
    13 
    14         public Int16? Status { get; set; }
    15         public DateTime CreateTime { get; set; }
    View Code

        1.2、填充数据

     1 public class DataInitEF :DropCreateDatabaseIfModelChanges<DAL.DBContext.DBContext>
     2     {
     3         protected override void Seed(DAL.DBContext.DBContext context)
     4         {
     5             #region
     6             SByte? status = 1;
     7             User userEntity = new User()
     8             {
     9                 Code = "admin",
    10                 Name = "管理员",
    11                 Status = status,
    12                 CreateTime = DateTime.Now
    13             };
    14 
    15             List<User> users = new List<User>();
    16 
    17             for (int i = 1; i <= 1000; i++)
    18             {
    19                 if (i % 7 == 0)
    20                 {
    21                     status = 2;
    22                 }
    23                 else if (i % 17 == 0)
    24                 {
    25                     status = 3;
    26                 }
    27                 else if (i % 27 == 0)
    28                 {
    29                     status = -1;
    30                 }
    31                 else
    32                 {
    33                     status = 1;
    34                 }
    35                 users.Add(new User()
    36                 {
    37                     Code = "user_" + i,
    38                     Name = "user_" + i,
    39                     Status = status,
    40                     CreateTime=DateTime.Now
    41                 });
    42             }
    43             context.User.Add(userEntity);
    44             context.User.AddRange(users);
    45             #endregion
    46 
    47             base.Seed(context);
    48         }
    49 
    50     }
    View Code

      2、封装Model服务对象  

     1 public interface IUserService: IBaseService
     2     {        
     3         UserPayResult Pay( string userAccount, decimal? payment);
     4     }
     5 
     6     public class UserService : EntityService, IUserService
     7     {
     8         [InjectionConstructor]//构造函数注入
     9         public UserService(DbContext dbContext) : base(dbContext)
    10         {
    11 
    12         }
    13 
    14       
    15         public UserPayResult Pay( string userAccount, decimal? payment)
    16         {
    17             UserPayResult result = null;
    18             if (!string.IsNullOrEmpty(userAccount))
    19             {
    20                 result = new UserPayResult()
    21                 {
    22                     UserAccount = userAccount,
    23                     Message = string.Format("{0}:本次成功消费{1}元!", userAccount, payment),
    24                     Status = 200,
    25                     RecTimeSpan = DateTime.Now
    26                 };
    27             }
    28             else
    29             {
    30                 result = new UserPayResult()
    31                 {
    32                     UserAccount = userAccount,
    33                     Message = "支付对象余额不足!",
    34                     Status = 500,
    35                     RecTimeSpan = DateTime.Now
    36                 };
    37             }
    38             return result;
    39         }
    40     }
    View Code

    上面封装了User的服务对象,并提供了接口的实现。

      3、测试  

     1  static void UserTest()
     2         {
     3             {
     4                 IUnityContainer unityContainer = ContainerFactory.GetContainerInstance();
     5 
     6               
     7                 IUserService userService = unityContainer.Resolve<IUserService>();
     8 
     9                 int inflCount = 0;
    10                 var listUser = userService.LoadEntities<User>();
    11                 inflCount = listUser.Count();
    12                 
    13 
    14                 userService.Dispose();
    15             }
    16         }
    View Code

    可以看到上面并没有具体的细节对象,使用的IUserService接口是通过容器注入的UserService对象,而UserService对象则继承了EntityService对象。这些注入动作通过ContainerFactory对象读取配置文件就已经完成。

    四、配置文件

    <configuration>
      <configSections>
      <!--configSections节点必须放在首位-->
        <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration"/>
      </configSections>
      <unity>
        <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension,Unity.Interception.Configuration"/>
        
        <containers>
          <container name="TestContainer">
            <!--AOP扩展-->
            <extension type="Interception"/>
            <!-- 完整的类型名称,程序集名称 -->
            <register type="System.Data.Entity.DbContext, EntityFramework" mapTo="DAL.DBContext.DBContext,DAL"  />
            <register type="DAL.Service.Interface.IBaseService, DAL" mapTo="DAL.Service.Class.EntityService, DAL" name="DAL.Service.Class.EntityService" />
            <register type="UI.Console.UI.Test.IUserService, UI.Console" mapTo="UI.Console.UI.Test.UserService, UI.Console"  >
              <interceptor type="InterfaceInterceptor"/><!--只能对接口做拦截,好处是只要目标类型实现了指定接口就可以拦截-->
              <interceptionBehavior type="Common.AOP.ExceptionLoggingBehavior, Common"/>             
              <lifetime type="transient" /><!--生命周期-->
              <constructor>
                <!--构造函数参数-->
                <param name="dbContext" type="System.Data.Entity.DbContext, EntityFramework"/>
              </constructor>
            </register>
          </container>
         
        </containers>
      
      </unity>
    </configuration>
    View Code

    配置文件格式:<register type="需要注入的类型, 程序集" mapTo="被注入的类型, 程序集"  />

    五、AOP实现 

     1 namespace Common.AOP
     2 {
     3     /// <summary>
     4     /// Unity为我们提供了一个IInterceptionBehavior接口需要实现这个接口
     5     /// 接口为我们提供了三个方式(GetRequiredInterfaces、Invoke、WillExecute)实现
     6     /// WillExecute表示是否执行该行为,如果是false这个方法被调用时,不会被捕捉。因为我们总是要执行的,所以为true
     7     /// GetRequiredInterfaces将你想要的接口类型和行为联系起来,我们暂时不需要,所以返回Type.EmptyTypes
     8     /// Invoke执行方式接口
     9     /// </summary>
    10     public class ExceptionLoggingBehavior : IInterceptionBehavior
    11     {
    12         public bool WillExecute
    13         {
    14             get { return true; }
    15         }
    16 
    17         public IEnumerable<Type> GetRequiredInterfaces()
    18         {
    19             return Type.EmptyTypes;
    20         }
    21 
    22         /// <summary>
    23         /// 拦截函数
    24         /// </summary>
    25         /// <param name="input"></param>
    26         /// <param name="getNext"></param>
    27         /// <returns></returns>
    28         public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
    29         {
    30             string info = string.Empty;
    31             info = string.Format("当前函数对象:{0},返回类型:{1}", input.MethodBase.Name, ((MethodInfo)(input.MethodBase)).ReturnType.FullName);
    32 
    33             try
    34             {
    35                 var methodReturn = getNext().Invoke(input, getNext);
    36                 if (methodReturn.Exception != null)
    37                 {
    38                     info += string.Format(" 执行失败:{0}", methodReturn.Exception.Message);
    39                 }
    40                 else
    41                 {
    42                     info += string.Format(" 执行成功!");
    43                 }
    44 
    45                 Console.WriteLine(info);
    46 
    47                 return methodReturn;
    48             }
    49             catch (Exception ex)
    50             {
    51                 info += string.Format(" 执行失败:{0}", ex.Message);
    52                 Console.WriteLine(info);
    53                 throw ex;
    54             }
    55         }
    56     }
    57 }
    View Code

    上面的配置文件中为IUserService接口注入了UserService对象,并且配置AOP对象,所以每当调用UserService对象的方法都会被ExceptionLoggingBehavior对象拦截。

     

      

  • 相关阅读:
    codeforces 671B Robin Hood 二分
    HDU 4009 Transfer water 最小树形图
    HDU 2121 Ice_cream’s world II 最小树形图
    UVA1395 Slim Span(枚举最小生成树)
    ZOJ 1107FatMouse and Cheese(BFS)
    POJ2239 Selecting Courses(二分图最大匹配)
    UVA 11419SAM I AM(输出 最小覆盖点 )
    POJ 3678 Katu Puzzle(强连通 法)
    POJ3207Ikki's Story IV
    POJ1236Network of Schools(强连通分量 + 缩点)
  • 原文地址:https://www.cnblogs.com/hua66/p/9670639.html
Copyright © 2011-2022 走看看