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的容器来创建 ...
随机推荐
- MySQL 上手教程
安装 通过官网选择版本下载安装.Mac 上可通过 Homebrew 方便地安装: $ brew install mysql 检查安装是否成功: $ mysql --version mysql Ver ...
- 基于udp的套接字编程
一,简单明了了解udp套接字编程 客户端: #Author : Kelvin #Date : 2019/1/30 11:07 from socket import * ip_conf=("1 ...
- 【重学计算机】操作系统D2章:处理器管理
1. 指令与处理器模式 指令执行周期:取指.译码.执行 指令分类(根据权限) 特权指令:只能被操作系统内核使用(启动IO,置PC值) 非特权指令:所有程序都能使用 处理器模式: 共有四种:0内核模式, ...
- asp.net core系列 60 Ocelot 构建服务认证示例
一.概述 在Ocelot中,为了保护下游api资源,用户访问时需要进行认证鉴权,这需要在Ocelot 网关中添加认证服务.添加认证后,ReRoutes路由会进行身份验证,并使用Ocelot的基于声明的 ...
- 非常贴心的轮子 FreeSql
FreeSql 项目从2018年11月28日开发至今,版本已发布至 v0.3.12,版本规则:年数-月-日-当日版本号.目前主要包括 FreeSql.FreeSql.Repository 两个项目的维 ...
- BugkuCTF~Mobile~WriteUp
最近,开始记录一篇关于 Android 逆向分析的 WriteUp 方便有需要的人学习,也欢迎大家相互交流, 发现不 一样的世界. 一. signin 考点:反编译.静态分析 Topic Link:h ...
- asp.net core 系列之并发冲突
本文介绍如何处理多个用户并发更新同一实体(同时)时出现的冲突 . 主要是两种:一种,检查属性并发冲突,使用 [ConcurrencyCheck] ;另一种,检测行的并发冲突,使用 rowversion ...
- Sql 优化解决方案
转自:https://blog.csdn.net/jie_liang/article/details/77340905 用以记录: 在sql查询中为了提高查询效率,我们常常会采取一些措施对查询语句进行 ...
- Deepin linux Compass.app安装
compass.app是集成了sass的工具,安装完Compass就能够使用sass. 首先,上官网 可以看到官网上推荐的两种sass使用方式,application&command line ...
- Git原理与命令大全
Git (wiki: en chs )是一个免费开源的分布式版本控制系统,由linux内核作者linus Torvalds开发,大型开源项目linux kernel.Android.chromium ...