IOC之Unity的使用详解
原文链接: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的使用详解的更多相关文章
- (转)java之Spring(IOC)注解装配Bean详解
java之Spring(IOC)注解装配Bean详解 在这里我们要详细说明一下利用Annotation-注解来装配Bean. 因为如果你学会了注解,你就再也不愿意去手动配置xml文件了,下面就看看 ...
- spring在IoC容器中装配Bean详解
1.Spring配置概述 1.1.概述 Spring容器从xml配置.java注解.spring注解中读取bean配置信息,形成bean定义注册表: 根据bean定义注册表实例化bean: 将bean ...
- spring的IOC,DI及案例详解
一:spring的基本特征 Spring是一个非常活跃的开源框架:它是一个基于Core来架构多层JavaEE系统的框架,它的主要目的是简化企业开发.Spring以一种非侵入式的方式来管理你的代码,Sp ...
- 一步一步造个IoC轮子(二),详解泛型工厂
一步一步造个Ioc轮子目录 一步一步造个IoC轮子(一):Ioc是什么 一步一步造个IoC轮子(二):详解泛型工厂 一步一步造个IoC轮子(三):构造基本的IoC容器 详解泛型工厂 既然我说IoC容器 ...
- Unity Built-in Shader详解二
这次主要讨论Unity自带的Shader中Transparent Shader Family 这个家族的Shader一共7种,原理和类型与Normal中的上差不多,只不过这些Shader是用在半透明或 ...
- Unity 坐标 转换 详解 World世界坐标 Screen屏幕坐标 View视口坐标 GUI坐标 NGUI坐标 localPosition相对父级坐标
在制作游戏中我们经常会遇到这样一个需求: 在人物模型的上面显示 名字.称号 一类的文字或者图片 如下图 人物模型属于是Camera1 UI Title信息属于NGUI Camera2 如下图 这时 ...
- java之Spring(IOC)注解装配Bean详解
在这里我们要详细说明一下利用Annotation-注解来装配Bean. 因为如果你学会了注解,你就再也不愿意去手动配置xml文件了,下面就看看Annotation的魅力所在吧. 先来看看之前的bean ...
- IOC和DI的区别详解
IOC 是英文inversion of control的缩写,意思是控制反转DI 是英文Dependency Injection的缩写,意思是依赖注入 下面用一个简单的例子来描述一下IOC和DI的 ...
- 关于 IOC和spring基本配置详解
Spring 中的两个概念 IOC控制反转(也叫依赖注入DI): AOP面向切面编程: 控制反转:当某个java对象需要(依赖)另一个java对象是,不是直接创建依赖对象,而是由实现IOC的容器来创建 ...
随机推荐
- OsharpNS轻量级.net core快速开发框架简明入门教程-从零开始启动Osharp
OsharpNS轻量级.net core快速开发框架简明入门教程 教程目录 从零开始启动Osharp 1.1. 使用OsharpNS项目模板创建项目 1.2. 配置数据库连接串并启动项目 1.3. O ...
- 10位时间戳使用moment转化为日期
前情提要: 需要把后台传过来的10位时间戳转化格式为:‘YYYY-MM-DD HH:mm:ss’的日期展示在页面上.本来是自己写了个函数,但是奈何leader说我们项目用了moment了,你为什么不用 ...
- 【ODI】| 数据ETL:从零开始使用Oracle ODI完成数据集成(三)
资料库的创建.体系结构的创建.模型反向工程都已经完成了,下面就是创建以及执行接口来完成工作了. 浏览前两节请点击: [ODI]| 数据ETL:从零开始使用Oracle ODI完成数据集成(一) [OD ...
- WebView,我已经长大了,知道自己区分是否安全了!
一.前言 如果你在用 Android 原生系统(Google Play 服务),在使用 WebView 加载某些网页时,一定遇到过以下的安全警告红屏. 这是 WebView 的安全浏览保护策略,在 A ...
- TensorFlow从1到2(六)结构化数据预处理和心脏病预测
结构化数据的预处理 前面所展示的一些示例已经很让人兴奋.但从总体看,数据类型还是比较单一的,比如图片,比如文本. 这个单一并非指数据的类型单一,而是指数据组成的每一部分,在模型中对于结果预测的影响基本 ...
- Python:requests:详解超时和重试
网络请求不可避免会遇上请求超时的情况,在 requests 中,如果不设置你的程序可能会永远失去响应.超时又可分为连接超时和读取超时. 连接超时 连接超时指的是在你的客户端实现到远端机器端口的连接时( ...
- Django学习之十二:Cache 缓存组件
目录 Django Cache 缓存组件 缓存逻辑伪代码 配置缓存源 可配置参数说明 01. Django的默认缓存 02. 基于Redis的django-redis 03. 自定义cache 04. ...
- HTML 练习拖动面板
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- ArcMap插件开发初识:Add In
之前一直在做ArcEngine的相关开发,做的winform相关,新换了工作,又开始新的学习旅程! Add In 这个东西很早就知道有,但是一直没有用过,因为之前的公司有自己框架,接口,虽然我也是做插 ...
- Maven 基本的认识
Maven 基本的认识 1. 什么是Maven? 在平时开发中,经常遇到某个jar包,我在代码层已经Import 和@Automation了,编译器还是提醒你某个jar包找不到,往往这时来个mvn i ...