原文链接: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. Text-CNN-文本分类-keras

    Text CNN 1. 简介 TextCNN 是利用卷积神经网络对文本进行分类的算法,由 Yoon Kim 在 "Convolutional Neural Networks for Sent ...

  2. 页面性能优化-原生JS实现图片懒加载

    在项目开发中,我们往往会遇到一个页面需要加载很多图片的情况.我们可以一次性加载全部的图片,但是考虑到用户有可能只浏览部分图片.所以我们需要对图片加载进行优化,只加载浏览器窗口内的图片,当用户滚动时,再 ...

  3. 5G+边缘计算,着眼可见的未来

    在 2019 年 2 月巴塞罗那举办的 MWC(世界移动通讯大会)上,华为手机带来了一款超薄的 5G 折叠屏手机 Mate X.这款手机将折叠屏和 5G 结合在一起,引起了不少人的关注与舆论,而昂贵的 ...

  4. Python:logging 的巧妙设计

    引言 logging 的基本用法网上很多,这里就不介绍了.在引入正文之前,先来看一个需求: 假设需要将某功能封装成类库供他人使用,如何处理类库中的日志? 数年前在一个 C# 开发的项目中,我用了这样的 ...

  5. Center a website:网页居中

    inside the <body> tags, using a "wrapper" div to control the whole section. HTML: &l ...

  6. CSS 火焰?不在话下

    正文从下面开始. 今天的小技巧是使用纯 CSS 生成火焰,逼真一点的火焰. 嗯,长什么样子?在 CodePen 上输入关键字 CSS Fire,能找到这样的: 或者这样的: 我们希望,仅仅使用 CSS ...

  7. openlayers4 入门开发系列之地图模态层篇(附源码下载)

    前言 openlayers4 官网的 api 文档介绍地址 openlayers4 api,里面详细的介绍 openlayers4 各个类的介绍,还有就是在线例子:openlayers4 官网在线例子 ...

  8. android Fragment中使用Toolbar

    在Activity中可以直接使用 setSupportActionBar(toolbar); 就可以重写 onCreateOptionsMenu 和 onOptionsItemSelected 方法: ...

  9. Flutter的初体验--初次配置的问题

    首先参照官方文档进行搭建Mac下的环境 ,然后就会遇到以下问题:   1.在下载了Flutter 之后,执行Flutter doctor之后,报错: Could not resolve URL &qu ...

  10. Windows Server 2016-Powershell新建用户补充

    前边我们介绍到Windows Server 2016-图形化新建域用户(一) 及 Windows Server 2016-批量新建域用户(二) ,里边提到了批量通过new-aduser常见帐号,这里简 ...