Autofac3 在MVC4中的运用原理
这是一种新的开发模式,注入开发模式,或者叫它IOC模式,说起IOC你可以这样去理解它,它为你的某个实现流出一个注入点,你生产的对象,可以根据你之前的配置进行组合。 IOC全称是Inversion of Control,即反转控制,或者说是依赖注入更为合适。选择别纠结这些全称的专业词。我们可以用别外一些方式去理解它,IOC,是一种设计模式。它的延生所要实现的是把藕合从代码中移出去,统一放到XML文件中,通过一个容器在需要的时候把这个依赖关系形成,即把需要的接口实现注入到需要它的类中,这可能就是“依赖注入”说法的来源了。
而注入点的位置及方式也是多种多样的,我们今天主要说一个通过HTTP请求进行注入的方式,IOC工具使用高效的Autofac,对它的认识你可以看这篇文章。
首先看一下我们这个项目的知识点:
MVC4一个对UI层进行分层的架构模式,在微软的MVC4中加入了开源的Razor引擎
EF(Entity Framework)这无疑是微软自己比较成功的ORM(Object Relational Mapping)工具(即对象关系映射,目前数据库是关系型数据库ORM 主要是把数据库中的关系数据映射称为程序中的对象),它执行效率上要高于linq to sql,甚至你自己编写的ado.net脚本。
Autofac这是在orchard项目中被广泛的IOC工具,它支持类型,反泛,HTTP等注入
对于这个系统的autofac部分,我们将它的注入点放在controller的构造函数中,将生产的对象配置在global中,当然,你也可以设置在config文件,或者你自己的文件中。
我认为它的工作方式应该是:
网站启动=>从global中得到ioc配置信息=>http request请求页面=>通过controller中的参数进行实现的创建=>action中使用创建好的对象
OK,有了这样一个理论基础,我们来看一下代码吧:
EF部分的DATA层
public partial class EfRepository<T> : IRepository<T> where T : class {
private readonly Guid _instanceId;
private readonly IDbContext _context;
private IDbSet<T> _entities;
public Guid InstanceId
{
get { return _instanceId; }
}
public EfRepository(IDbContext context)
{
AutoCommitEnabled = true;
this._context = context;
_instanceId = Guid.NewGuid();
}
public T GetById(object id)
{
return this._entities.Find(id);
}
public T Create()
{
return this.Entities.Create();
}
public void Insert(T entity)
{
try
{
if (entity == null)
throw new ArgumentNullException("entity");
this.Entities.Add(entity);
if (this.AutoCommitEnabled)
_context.SaveChanges();
}
catch(DbEntityValidationException dbEx)
{
var msg = string.Empty;
foreach(var validationErrors in dbEx.EntityValidationErrors)
foreach (var validationError in validationErrors.ValidationErrors)
msg += string.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage) + Environment.NewLine;
var fail = new Exception(msg, dbEx);
throw fail;
}
} public void InsertRange(IEnumerable<T> entities, int batchSize = )
{
try
{
if (entities == null)
throw new ArgumentNullException("entities");
if (entities.HasItems())
{
if (batchSize <= )
{
entities.Each(x => this.Entities.Add(x));
if (this.AutoCommitEnabled)
_context.SaveChanges();
}
else
{
int i = ;
bool saved = false;
foreach (var entity in entities)
{
this.Entities.Add(entity);
saved = false;
if (i % batchSize == )
{
if (this.AutoCommitEnabled)
_context.SaveChanges();
i = ;
saved = true;
}
i++;
}
if (!saved)
{
if (this.AutoCommitEnabled)
_context.SaveChanges();
}
}
}
}
catch (DbEntityValidationException ex)
{
throw ex;
}
}
public void Update(T entity)
{
if (entity == null)
throw new ArgumentNullException("entity");
try
{
if (this.InternalContext.Entry(entity).State == EntityState.Detached)
{
var set = Entities;
T attachedEntity = set.Find(entity.Key); // You need to have access to key if (attachedEntity != null)
{
var attachedEntry = this.InternalContext.Entry(attachedEntity);
attachedEntry.CurrentValues.SetValues(entity);
}
else
{
// This should attach entity
this.InternalContext.Entry(entity).State = EntityState.Modified;
}
}
}
finally { } if (AutoCommitEnabled)
_context.SaveChanges();
} public void Delete(T entity)
{
if (entity == null)
throw new ArgumentNullException("entity");
if(InternalContext.Entry(entity).State==EntityState.Detached)
{
this.Entities.Attach(entity);
}
this.Entities.Remove(entity);
if (this.AutoCommitEnabled)
_context.SaveChanges();
} public IDictionary<string, object> GetModifiedProperties(T entity)
{
var props = new Dictionary<string, object>(); var ctx = InternalContext;
var entry = ctx.Entry(entity);
var modifiedPropertyNames = from p in entry.CurrentValues.PropertyNames
where entry.Property(p).IsModified
select p;
foreach (var name in modifiedPropertyNames)
{
props.Add(name, entry.Property(name).OriginalValue);
} return props;
}
public virtual IQueryable<T> Table
{
get
{
return this.Entities;
}
} public int Commit()
{
try
{
return this._context.SaveChanges();
}
catch(DbEntityValidationException dbEx)
{
var msg = string.Empty;
foreach (var validationErrors in dbEx.EntityValidationErrors)
foreach (var validationError in validationErrors.ValidationErrors)
msg += Environment.NewLine + string.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage); var fail = new Exception(msg, dbEx);
throw fail;
}
}
#region Helpers
protected internal dwDbContextBase InternalContext
{
get { return _context as dwDbContextBase; }
}
public bool AutoCommitEnabled { get; set; } private DbSet<T> Entities
{
get
{
if (_entities == null) { _entities = _context.Set<T>(); }
return _entities as DbSet<T>;
}
} #endregion public IQueryable<T> Include(IQueryable<T> query,string path)
{
Guard.ArgumentNotNull(query, "query");
Guard.ArgumentNotEmpty(path, "path");
return query.Include(path);
}
public IQueryable<T> Include<TProperty>(IQueryable<T> query,Expression<Func<T,TProperty>> path)
{
Guard.ArgumentNotNull(query, "query");
Guard.ArgumentNotNull(path, "path");
return query.Include(path);
}
public IDbContext Context
{
get { return _context; }
} }
Services层(BLL层)核心代码:
public class TestService : BaseService, ITestService
{
private const string IncludeProperties = "";
private readonly IRepository<Tests> _repository;
private readonly ICacheManager _cacheManager;
private readonly IExporter _exporter;
public IList<Tests> GetAll()
{
return _repository.FindBy(null, null, IncludeProperties).ToList();
} public TestService(IRepository<Tests> repository,
ICacheManager cacheManager,IExporter exporter,
IEventPublisher eventPublisher):base(eventPublisher)
{
_repository = repository;
_exporter = exporter;
_cacheManager = cacheManager;
} }
WEB层MVC部分代码:(注意:我们的WEB层不应该有对DATA层的引用,WEB层一般只注入SERVICE的对象,这一点是需要注意的,即不要直接调用数据库仓库)
public class TestController : ApiController
{
private readonly ITestService _service;
private readonly Func<Tests, TestsModel, TestsModel> _convertCallback = (entity, model) => { return model; };
public TestController(ITestService service) { _service = service; }
public IEnumerable<TestsModel> Get()
{
var items = _service.GetAll();
var model = items.ConvertTo(_convertCallback);
return model;
}
而注入参数我们放在global中,看一下核心代码:
//初始化依赖注入组件
var bootStrapper = new AutofacBootStrapper();
BootStrapperManager.Initialize(bootStrapper);
//设置依赖注入
GlobalConfiguration.Configuration.DependencyResolver = bootStrapper.GetWebApiDependencyResolver();
DependencyResolver.SetResolver(bootStrapper.GetMvcDependencyResolver());
builder.Register(c => new dwObjectContext("MyConnection")).As<IDbContext>().InstancePerHttpRequest().InstancePerApiRequest();
builder.RegisterGeneric(typeof(EfRepository<>)).As(typeof(IRepository<>)).InstancePerHttpRequest().InstancePerApiRequest(); //注册缓存类型
builder.RegisterType<StaticCache>().As<ICache>().Named<ICache>(YB_CACHE_STATIC).SingleInstance();
builder.RegisterType<RequestCache>().As<ICache>().Named<ICache>(YB_CACHE_PER_REQUEST).InstancePerHttpRequest().InstancePerApiRequest();
//注册缓存控制类型
builder.RegisterType<NullCacheManager>()
.As<ICacheManager>()
.Named<ICacheManager>(YB_SM_CACHE_NULL)
.WithParameter(ResolvedParameter.ForNamed<ICache>(YB_CACHE_STATIC))
.SingleInstance(); builder.RegisterType<DefaultCacheManager>()
.As<ICacheManager>()
.Named<ICacheManager>(YB_SM_CACHE_PER_REQUEST)
.WithParameter(ResolvedParameter.ForNamed<ICache>(YB_CACHE_PER_REQUEST))
.InstancePerHttpRequest().InstancePerApiRequest(); builder.RegisterType<DefaultCacheManager>()
.As<ICacheManager>()
//.Named<ICacheManager>(YB_SM_CACHE_STATIC)
.WithParameter(ResolvedParameter.ForNamed<ICache>(YB_CACHE_STATIC))
.SingleInstance(); var assembly = Assembly.GetExecutingAssembly();
//注册所有 MVC 控制器
builder.RegisterControllers(assembly)
.InstancePerHttpRequest();
//注册所有 Web Api 控制器
builder.RegisterApiControllers(assembly)
.InstancePerApiRequest();
Autofac3 在MVC4中的运用原理的更多相关文章
- C#面试题(转载) SQL Server 数据库基础笔记分享(下) SQL Server 数据库基础笔记分享(上) Asp.Net MVC4中的全局过滤器 C#语法——泛型的多种应用
C#面试题(转载) 原文地址:100道C#面试题(.net开发人员必备) https://blog.csdn.net/u013519551/article/details/51220841 1. . ...
- MVC4中基于bootstrap和HTML5的图片上传Jquery自定义控件
场景:mvc4中上传图片,批量上传,上传前浏览,操作.图片进度条. 解决:自定义jquery控件 没有解决:非图片上传时,会有浏览样式的问题; 解决方案; 1.样式 – bootstrap 的css和 ...
- Autofac在MVC4中牛刀小试
Autofac是传说中速度最快的一套.NET高效的依赖注入框架.Autofac的介绍与使用请去参考Autofac全面解析系列(版本:3.5). 这里介绍的已经挺详细的啦. 下面我就先来说说MVC4 ...
- ASP.NET MVC4中的bundles特性引发服务器拒绝访问(403错误)
在ASP.NET MVC4中微软引入了bundles特性,这个特性可以将服务器端的多个Javascript或多个css文件捆绑在一起作为一个单一的URL地址供客户端浏览器调用,从而减少了页面上Http ...
- 广告系统中weak-and算法原理及编码验证
wand(weak and)算法基本思路 一般搜索的query比较短,但如果query比较长,如是一段文本,需要搜索相似的文本,这时候一般就需要wand算法,该算法在广告系统中有比较成熟的应 该,主要 ...
- ABP中动态WebAPI原理解析
ABP中动态WebAPI原理解析 动态WebAPI应该算是ABP中最Magic的功能之一了吧.开发人员无须定义继承自ApiController的类,只须重用Application Service中的类 ...
- MVC4中使用Ninject
MVC4中使用Ninject 1.NuGet获取Ninject.dll .NET技术交流群 199281001 .欢迎加入. 2.全局注册 Global.asax.cs RegisterNinje ...
- mvc4中jquery-ui日期控件datepicker的应用
mvc4中jquery-ui日期控件datepicker的应用 本文适合mvc中日期选择需要的同学: 假设读者已经具备了mvc4和javascript中的相关知识 一. 开始项目之前把项目中目录:/C ...
- WebSocket在ASP.NET MVC4中的简单实现
WebSocket在ASP.NET MVC4中的简单实现 2013-12-21 20:48 by 小白哥哥, 810 阅读, 3 评论, 收藏, 编辑 WebSocket 规范的目标是在浏览器中实现和 ...
随机推荐
- Apache -- 利用.htaccess防盗链
在Apache服务器的前提下利用.htaccess文件来防盗链的原理是通过检查图片或文件请求头信息中的Referer属性(也就是请求的来源),判断它是否属于你所规定的合法的请求来源,从而实现让合法来源 ...
- 【原创】LogCat信息演示Activity生命周期
界面如下:注意:这是在手机.竖屏状态下! (一)1个Activity /** * 7个方法 * 测试1个Activity的生命周期 * * LogCat: ...
- Java常量定义需要注意的两点
在任何开发语言中,都需要定义常量.在Java开发语言平台中也不例外.不过在Java常量定义的时候,跟其他语言有所不同.其有自己的特色.在这篇文章中,主要针对Java语言中定义常量的注意事项进行解析,帮 ...
- POJ 1286 Necklace of Beads(Polya简单应用)
Necklace of Beads 大意:3种颜色的珠子,n个串在一起,旋转变换跟反转变换假设同样就算是同一种,问会有多少种不同的组合. 思路:正规学Polya的第一道题,在楠神的带领下,理解的还算挺 ...
- 判断openfire用户的状态
/** * 判断openfire用户的状态 * 说明 :必须要 openfire加载 presence 插件,同时设置任何人都可以访问 * /status?jid=user1@my.openfire. ...
- 【转 :Hibernate 缓存机制】
转自:http://www.cnblogs.com/wean/archive/2012/05/16/2502724.html Hibernate 缓存机制 一.why(为什么要用Hibernate缓存 ...
- python笔记3-邮件发送(smtplib)
前言 本篇总结了QQ邮箱和163邮箱发送邮件,邮件包含html中文和附件,可以发给多个收件人,专治各种不行,总之看完这篇麻麻再也不用担心我的邮件收不到了. 以下代码兼容python2和python3, ...
- Spring+Mybatis+SpringMVC后台与前台分页展示实例(附工程)
林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 摘要:本文实现了一个后台由Spring+Mybatis+SpringMVC组成,分页采用Pag ...
- 织梦(Dedecms)select_soft_post.php页面变量未初始漏洞
漏洞版本: Dedecms 5.5 漏洞描述: 漏洞产生文件位于include\dialog\select_soft_post.php,其变量$cfg_basedir没有正确初始化,导致可以饶过身份认 ...
- drawable和values的加载规则
Google搞了一大套hdpi.xhdpi之类的这些东西,简单说来,就是为了让我们轻松实现"与设备密度无关的视觉大小一致性",注意这里的"视觉大小一致性",就是 ...