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

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

一、封装数据访问层

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

 public interface IBaseService : IDisposable
{
T FindEntity<T>(int id) where T : class;
void AddEntity<T>(T entity) where T : class;
Task<int> AddEntities<T>(IEnumerable<T> entities) where T : class;
void UpdateEntity<T>(T entity) where T : class;
Task<int> UpdateEntities<T>(IEnumerable<T> entities) where T : class;
void DeleteEntity<T>(int id) where T : class;
void DeleteEntity<T>(T entity) where T : class;
Task<int> DeleteEntities<T>(IEnumerable<T> entities) where T : class;
Task<int> DeleteEntities<T>(Func<T, bool> whereLambda) where T : class;
IQueryable<T> LoadEntities<T>() where T : class;
IQueryable<T> LoadEntities<T>(Func<T, bool> whereLambda) where T : class;
IQueryable<T> LoadEntities<T>(Func<T, bool> whereLambda, int pageSize, int pageIndex, out int count) where T : class;
IQueryable<T> ExcuteQuery<T>(string sql, SqlParameter[] parameters) where T : class;
void Excute<T>(string sql, SqlParameter[] parameters) where T : class;
int Commit();
Task<int> CommitAsync(); }

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

 public abstract class EntityService : IBaseService
{
protected DbContext DBContext { get; private set; }
public EntityService(DbContext dbContext)
{
this.DBContext = dbContext;
}
public T FindEntity<T>(int id) where T : class
{
T entity = this.DBContext.Set<T>().Find(id);
return entity;
}
public void AddEntity<T>(T entity) where T : class
{
this.DBContext.Entry(entity).State = EntityState.Added;
} [Obsolete("不建议使用基于EF实现批量操作函数,此操作已异步提交!", false)]
public Task<int> AddEntities<T>(IEnumerable<T> entities) where T : class
{
this.DBContext.Set<T>().AddRange(entities);
return this.CommitAsync();
}
public void UpdateEntity<T>(T entity) where T : class
{
this.DBContext.Entry(entity).State = EntityState.Modified;
//this.DBContext.Set<T>().Attach(entity);
//this.DBContext.Entry(entity).Property("")
} [Obsolete("不建议使用基于EF实现批量操作函数,此操作已异步提交!", false)]
public Task<int> UpdateEntities<T>(IEnumerable<T> entities) where T : class
{
this.DBContext.Configuration.AutoDetectChangesEnabled = false;
foreach (var entity in entities)
{
this.DBContext.Entry(entity).State = EntityState.Modified;
}
this.DBContext.Configuration.AutoDetectChangesEnabled = true;
//this.DBContext.Entry(entities).State= EntityState.Modified;
return this.CommitAsync();
}
public void DeleteEntity<T>(int id) where T : class
{ T entity = this.DBContext.Set<T>().Find(id);
this.DBContext.Set<T>().Remove(entity);
}
public void DeleteEntity<T>(T entity) where T : class
{
this.DBContext.Set<T>().Attach(entity);
this.DBContext.Entry(entity).State = EntityState.Deleted;
} [Obsolete("不建议使用基于EF实现批量操作函数,此操作已异步提交!", false)]
public Task<int> DeleteEntities<T>(IEnumerable<T> entities) where T : class
{
//this.DBContext.Configuration.AutoDetectChangesEnabled = false;
//foreach (var entity in entities)
//{
// this.DBContext.Entry(entity).State = EntityState.Deleted;
//}
//this.DBContext.Configuration.AutoDetectChangesEnabled = true;
this.DBContext.Set<T>().RemoveRange(entities);
return this.CommitAsync();
} [Obsolete("不建议使用基于EF实现批量操作函数,此操作已异步提交!", false)]
public Task<int> DeleteEntities<T>(Func<T, bool> whereLambda) where T : class
{
IQueryable<T> entities = this.DBContext.Set<T>().Where(whereLambda).AsQueryable();
//this.DBContext.Entry(entities).State = EntityState.Deleted;
this.DBContext.Set<T>().RemoveRange(entities);
return this.CommitAsync();
}
public IQueryable<T> LoadEntities<T>() where T : class
{
return this.DBContext.Set<T>();
}
public IQueryable<T> LoadEntities<T>(Func<T, bool> whereLambda) where T : class
{
return this.DBContext.Set<T>().Where<T>(whereLambda).AsQueryable();
}
public IQueryable<T> LoadEntities<T>(Func<T, bool> whereLambda, int pageSize, int pageIndex, out int count) where T : class
{
count = ;
count = this.DBContext.Set<T>().Where(whereLambda).AsQueryable().Count();
//return this.DBContext.Set<T>().Where<T>(whereLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsQueryable();
return this.DBContext.Set<T>().Where(whereLambda).Skip((pageIndex - ) * pageSize).Take(pageSize).AsQueryable();
} #region
public virtual int Commit()
{
return this.DBContext.SaveChanges();
}
public virtual Task<int> CommitAsync()
{
return this.DBContext.SaveChangesAsync();
}
#endregion
public virtual void Dispose()
{
if (this.DBContext!=null)
{
this.DBContext.Dispose();
}
} public IQueryable<T> ExcuteQuery<T>(string sql, SqlParameter[] parameters) where T : class
{
return this.DBContext.Database.SqlQuery<T>(sql, parameters).AsQueryable();
} public void Excute<T>(string sql, SqlParameter[] parameters) where T : class
{
DbContextTransaction trans = null;
try
{
trans = this.DBContext.Database.BeginTransaction();
this.DBContext.Database.ExecuteSqlCommand(sql, parameters);
trans.Commit();
}
catch (Exception ex)
{
if (trans != null)
trans.Rollback();
throw ex;
}
}
}

二、封装Unity容器对象  

  public class ContainerFactory
{
private static IUnityContainer _iUnityContainer = null;
private ContainerFactory()
{ }
static ContainerFactory()
{
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "CfgFiles\\Unity.Config.xml");//找配置文件的路径
Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName); _iUnityContainer = new UnityContainer();
section.Configure(_iUnityContainer, "TestContainer");
} public static IUnityContainer GetContainerInstance()
{
return _iUnityContainer;
}
}

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

三、示例

  1、用Code First初始化DB

    1.1、Models    

 [TableAttribute("Base_Sys_User")]
public class User
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; } [Column("Account")]
[StringLength()]
public String Code { get; set; } [StringLength()]
public String Name { get; set; } public Int16? Status { get; set; }
public DateTime CreateTime { get; set; }

    1.2、填充数据

 public class DataInitEF :DropCreateDatabaseIfModelChanges<DAL.DBContext.DBContext>
{
protected override void Seed(DAL.DBContext.DBContext context)
{
#region
SByte? status = ;
User userEntity = new User()
{
Code = "admin",
Name = "管理员",
Status = status,
CreateTime = DateTime.Now
}; List<User> users = new List<User>(); for (int i = ; i <= ; i++)
{
if (i % == )
{
status = ;
}
else if (i % == )
{
status = ;
}
else if (i % == )
{
status = -;
}
else
{
status = ;
}
users.Add(new User()
{
Code = "user_" + i,
Name = "user_" + i,
Status = status,
CreateTime=DateTime.Now
});
}
context.User.Add(userEntity);
context.User.AddRange(users);
#endregion base.Seed(context);
} }

  2、封装Model服务对象  

 public interface IUserService: IBaseService
{
UserPayResult Pay( string userAccount, decimal? payment);
} public class UserService : EntityService, IUserService
{
[InjectionConstructor]//构造函数注入
public UserService(DbContext dbContext) : base(dbContext)
{ } public UserPayResult Pay( string userAccount, decimal? payment)
{
UserPayResult result = null;
if (!string.IsNullOrEmpty(userAccount))
{
result = new UserPayResult()
{
UserAccount = userAccount,
Message = string.Format("{0}:本次成功消费{1}元!", userAccount, payment),
Status = ,
RecTimeSpan = DateTime.Now
};
}
else
{
result = new UserPayResult()
{
UserAccount = userAccount,
Message = "支付对象余额不足!",
Status = ,
RecTimeSpan = DateTime.Now
};
}
return result;
}
}

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

  3、测试  

  static void UserTest()
{
{
IUnityContainer unityContainer = ContainerFactory.GetContainerInstance(); IUserService userService = unityContainer.Resolve<IUserService>(); int inflCount = ;
var listUser = userService.LoadEntities<User>();
inflCount = listUser.Count(); userService.Dispose();
}
}

可以看到上面并没有具体的细节对象,使用的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>

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

五、AOP实现 

 namespace Common.AOP
{
/// <summary>
/// Unity为我们提供了一个IInterceptionBehavior接口需要实现这个接口
/// 接口为我们提供了三个方式(GetRequiredInterfaces、Invoke、WillExecute)实现
/// WillExecute表示是否执行该行为,如果是false这个方法被调用时,不会被捕捉。因为我们总是要执行的,所以为true
/// GetRequiredInterfaces将你想要的接口类型和行为联系起来,我们暂时不需要,所以返回Type.EmptyTypes
/// Invoke执行方式接口
/// </summary>
public class ExceptionLoggingBehavior : IInterceptionBehavior
{
public bool WillExecute
{
get { return true; }
} public IEnumerable<Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
} /// <summary>
/// 拦截函数
/// </summary>
/// <param name="input"></param>
/// <param name="getNext"></param>
/// <returns></returns>
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
string info = string.Empty;
info = string.Format("当前函数对象:{0},返回类型:{1}", input.MethodBase.Name, ((MethodInfo)(input.MethodBase)).ReturnType.FullName); try
{
var methodReturn = getNext().Invoke(input, getNext);
if (methodReturn.Exception != null)
{
info += string.Format(" 执行失败:{0}", methodReturn.Exception.Message);
}
else
{
info += string.Format(" 执行成功!");
} Console.WriteLine(info); return methodReturn;
}
catch (Exception ex)
{
info += string.Format(" 执行失败:{0}", ex.Message);
Console.WriteLine(info);
throw ex;
}
}
}
}

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

 

  

IOC之Unity的使用详解的更多相关文章

  1. (转)java之Spring(IOC)注解装配Bean详解

    java之Spring(IOC)注解装配Bean详解   在这里我们要详细说明一下利用Annotation-注解来装配Bean. 因为如果你学会了注解,你就再也不愿意去手动配置xml文件了,下面就看看 ...

  2. spring在IoC容器中装配Bean详解

    1.Spring配置概述 1.1.概述 Spring容器从xml配置.java注解.spring注解中读取bean配置信息,形成bean定义注册表: 根据bean定义注册表实例化bean: 将bean ...

  3. spring的IOC,DI及案例详解

    一:spring的基本特征 Spring是一个非常活跃的开源框架:它是一个基于Core来架构多层JavaEE系统的框架,它的主要目的是简化企业开发.Spring以一种非侵入式的方式来管理你的代码,Sp ...

  4. 一步一步造个IoC轮子(二),详解泛型工厂

    一步一步造个Ioc轮子目录 一步一步造个IoC轮子(一):Ioc是什么 一步一步造个IoC轮子(二):详解泛型工厂 一步一步造个IoC轮子(三):构造基本的IoC容器 详解泛型工厂 既然我说IoC容器 ...

  5. Unity Built-in Shader详解二

    这次主要讨论Unity自带的Shader中Transparent Shader Family 这个家族的Shader一共7种,原理和类型与Normal中的上差不多,只不过这些Shader是用在半透明或 ...

  6. Unity 坐标 转换 详解 World世界坐标 Screen屏幕坐标 View视口坐标 GUI坐标 NGUI坐标 localPosition相对父级坐标

    在制作游戏中我们经常会遇到这样一个需求: 在人物模型的上面显示 名字.称号 一类的文字或者图片 如下图 人物模型属于是Camera1   UI Title信息属于NGUI Camera2 如下图 这时 ...

  7. java之Spring(IOC)注解装配Bean详解

    在这里我们要详细说明一下利用Annotation-注解来装配Bean. 因为如果你学会了注解,你就再也不愿意去手动配置xml文件了,下面就看看Annotation的魅力所在吧. 先来看看之前的bean ...

  8. IOC和DI的区别详解

    IOC 是英文inversion of control的缩写,意思是控制反转DI 是英文Dependency Injection的缩写,意思是依赖注入   下面用一个简单的例子来描述一下IOC和DI的 ...

  9. 关于 IOC和spring基本配置详解

    Spring 中的两个概念 IOC控制反转(也叫依赖注入DI): AOP面向切面编程: 控制反转:当某个java对象需要(依赖)另一个java对象是,不是直接创建依赖对象,而是由实现IOC的容器来创建 ...

随机推荐

  1. GT工具中用到的英文词解释

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px ".PingFang SC"; color: #454545 } p.p2 ...

  2. 审计篇丨PHPcms9.6.3后台XSS审计

    引言 今天与大家分享的文章是关于审计思路的知识点,用到的是PHPcms的最新版本,因为常规扫描无法进入后台,所以我们修改了代码让扫描器爬虫爬到后台. 漏洞复现环境 安装PHPstudy 安装PHPcm ...

  3. PHP过滤数组中的空值

    php对数组的操作已经很完善了,提供给我们很多内置函数用以操作数组,其实可以用array_filter函数对PHP数组中的控制进行过滤 array_filter() 函数用回调函数过滤数组中的值.该函 ...

  4. Akka实践一些总结

    最近在一些服务中使用了akka,主要用来做异步解耦和本地消息分发(路由),这里简单总结一下用法. 与spring集成 网上有不少集成的例子,要使用到spring的扩展. 我这边没有这样处理,而是简单把 ...

  5. gorm的日志模块源码解析

    gorm的日志模块源码解析 如何让gorm的日志按照我的格式进行输出 这个问题是<如何为gorm日志加traceId>之后,一个群里的朋友问我的.如何让gorm的sql日志不打印到控制台, ...

  6. Kubernetes的DaemonSet(下篇)

    用Daemon Pod来进行通信 使用Pod来再DaemonSet中通信的手段有: 推的方式:在DaemonSet中的Pod会被配置成发送更新到如状态数据库这样的服务.这些都没有客户端. IP+端口方 ...

  7. org.springframework.cache.interceptor.SimpleKey cannot be cast to java.lang.String

    springboot整合redis时,使用@Cacheable注解,如果方法的key参数为空,就会报org.springframework.cache.interceptor.SimpleKey ca ...

  8. Python 转化成 PB 格式数据

    一.概述 Protocol Buffers 是 Google 公司开发的一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化.它很适合做数据存储或 RPC 数据交换格式.可用于通讯 ...

  9. Java消息系统简单设计与实现

    前言:由于导师在我的毕设项目里加了消息系统(本来想水水就过的..),没办法...来稍微研究研究吧..简单简单... 需求分析 我的毕设是一个博客系统,类似于简书这样的,所以消息系统也类似,在用户的消息 ...

  10. 粮草先行——Android折叠屏开发技术点(二)

    继该系列的第一篇和番外篇之后,今天我们来聊一聊多窗口开发的注意事项.实际上,与其说"多窗口开发",不如说让我们的APP适应多窗口模式. 可能有朋友会问,为什么要提到多窗口模式呢? ...