介绍了下MEF的基础用法,让我们对MEF有了一个抽象的认识。当然MEF的用法可能不限于此,比如MEF的目录服务、目录筛选、重组部件等高级应用在这里就不做过多讲解,因为博主觉得这些用法只有在某些特定的环境下面才会用到,着实不太普遍,感觉没有钻下去的必要。如果你有兴趣也可以去了解下。这篇打算将MEF和仓储模式结合起来谈谈MEF在项目中的使用。

1、仓储模式:也叫Repository模式。Repository是一个独立的层,介于领域层与数据映射层(数据访问层)之间。它的存在让领域层感觉不到数据访问层的存在,它提供一个类似集合的接口提供给领域层进行领域对象的访问。Repository是仓库管理员,领域层需要什么东西只需告诉仓库管理员,由仓库管理员把东西拿给它,并不需要知道东西实际放在哪。Repository模式一般是用来封装数据访问层的,这也就是为什么很多地方看到说的什么“数据仓储”,大概就是这个意思。Repository模式并不是本文的重点,这里就不再展开,后面会单独分享这块。

关于仓储模式有以下几点需要注意:

(1)Repository模式是架构模式,在设计架构时,才有参考价值;

(2)Repository模式使用的意义:一是隔离业务逻辑层和底层数据访问层,保证数据出入口的唯一性;二是Repository模式针对聚合根设计的,而并不是针对表和实体设计的,换句话说,使用Repository是为了实现内聚,前端只负责向Repository请求数据即可,而不用关心数据的具体来源;

(3)Repository模式实际用途:更换、升级ORM引擎,不影响业务逻辑;

上面这些东西写得有点官方。博主的理解是,仓储模式就是对数据访问层(或者叫数据映射层)做了一层包装,每一次前端需要查询什么数据或者提交什么数据的时候,都是通过仓储对象Repository去操作的,前端基本上感觉不到数据访问层的存在。这样说你有没有好理解一点呢?没有?好吧,我们来看Demo。

2、MEF在仓储模式上面的应用:由于框架使用的是EF,所以这里也用EF结合仓储模式进行讲解。为了省略Repository模式的复杂结构,我们仅仅通过仓储的Save方法来说明。

IRepository<TEntity>接口以及实现代码:

public interface IRepository<T>
where T : BaseEntity
{
T Save(T entitiy);
}
[Export(typeof(IRepository<BaseEntity>))]
public abstract class Repository<T> : IRepository<T> where T : BaseEntity
{
//工作单元
[Import]
protected IUnitOfWork context { set; get; } private IDbSet<T> _entities; //注册MEF
public Repository()
{
Register.regisgter().ComposeParts(this);
} public virtual T Save(T entitiy)
{
if (entitiy == null) throw new ArgumentException("entitiy nul");
context.Save<T>(entitiy);
return entitiy;
}
} public static class Register
{
public static CompositionContainer regisgter()
{
var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
var container = new CompositionContainer(catalog);
return container;
}
}

BaseEntity是一个EF实体的公共基类,定义EF实体必须要遵循的约束。

IUnitOfWork工作单元接口以及实现

public interface IUnitOfWork : IDisposable
{
int Commit(); void Rollback(); void Save<T>(T entity) where T : BaseEntity;
}
/// <summary>
/// 单元操作实现
/// </summary>
     [Export(typeof(IUnitOfWork))]
public abstract class UnitOfWorkContextBase : IUnitOfWork
{
[ImportMany]
protected abstract IEnumerable<DbContext> Contexts { get; }
protected abstract DbContext Cur_context { get; set; } public UnitOfWorkContextBase()
{
          Register.regisgter().ComposeParts(this);
if (Contexts.Count() <= )
{
throw new Exception();
}
Cur_context = Contexts.FirstOrDefault();
} /// <summary>
/// 获取 当前单元操作是否已被提交
/// </summary>
public bool IsCommitted { get; private set; } /// <summary>
/// 提交当前单元操作的结果
/// </summary>
/// <returns></returns>
public int Commit()
{
if (IsCommitted)
{
return ;
}
try
{
int result = Cur_context.SaveChanges();
IsCommitted = true;
return result;
}
catch (DbUpdateException e)
{
if (e.InnerException != null && e.InnerException.InnerException is SqlException)
{
SqlException sqlEx = e.InnerException.InnerException as SqlException;
string msg = DataHelper.GetSqlExceptionMessage(sqlEx.Number);
throw PublicHelper.ThrowDataAccessException("提交数据更新时发生异常:" + msg, sqlEx);
}
throw;
}
} /// <summary>
/// 把当前单元操作回滚成未提交状态
/// </summary>
public void Rollback()
{
IsCommitted = false;
} public void Dispose()
{
if (!IsCommitted)
{
Commit();
}
Cur_context.Dispose();
} public void Save<T>(T entity) where T : T
{
Cur_context.SaveChanges();
}
}

既然这里使用了ImportMany,那么肯定有一个地方需要Export。我们使用EF新建一个edmx文件,在生成的上下文对象上面加上Export

[Export(typeof(DbContext))]
public partial class Entities : DbContext
{
public Entities()
: base("name=Entities")
{
} protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
} public DbSet<TB_USERS> TB_USERS { get; set; }
}

这里为什么要使用ImportMany?前面说了,仓储的好处之一在于对数据访问层做封装,使得前端不比关心数据的具体来源。当我们再建一个数据库连接的edmx时,我们只需要修改仓储里面的Cur_context 这个对象的赋值即可,由于其他地方都是针对Cur_context这一个上下文对象做的操作,所以基本都不需要做很大的变化。绕了这么大一圈,其实博主只是想说明Import和ImportMany和仓储模式结合使用的好处,至于仓储模式的适用性问题不是本文的重点。

MEF实现设计上的“松耦合”(二)的更多相关文章

  1. C#进阶系列——MEF实现设计上的“松耦合”(二)

    前言:前篇 C#进阶系列——MEF实现设计上的“松耦合”(一) 介绍了下MEF的基础用法,让我们对MEF有了一个抽象的认识.当然MEF的用法可能不限于此,比如MEF的目录服务.目录筛选.重组部件等高级 ...

  2. C#进阶系列——MEF实现设计上的“松耦合”(四):构造函数注入

    前言:今天十一长假的第一天,本因出去走走,奈何博主最大的乐趣是假期坐在电脑前看各处堵车,顺便写写博客,有点收获也是好的.关于MEF的知识,之前已经分享过三篇,为什么有今天这篇?是因为昨天分享领域服务的 ...

  3. MEF实现设计上的“松耦合”

    C#进阶系列——MEF实现设计上的“松耦合”(二)   前言:前篇 C#进阶系列——MEF实现设计上的“松耦合”(一) 介绍了下MEF的基础用法,让我们对MEF有了一个抽象的认识.当然MEF的用法可能 ...

  4. C#进阶系列——MEF实现设计上的“松耦合”(一)

    前言:最近去了趟外地出差,介绍推广小组开发的框架类产品.推广对象是本部门在项目上面的同事——1到2年工作经验的初级程序员.在给他们介绍框架时发现很多框架设计层面的知识他们都没有接触过,甚至没听说过,这 ...

  5. MEF实现设计上的“松耦合”(一)

    1.什么是MEF 先来看msdn上面的解释:MEF(Managed Extensibility Framework)是一个用于创建可扩展的轻型应用程序的库. 应用程序开发人员可利用该库发现并使用扩展, ...

  6. C#进阶系列——MEF实现设计上的“松耦合”(终结篇:面向接口编程)

    序:忙碌多事的八月带着些许的倦意早已步入尾声,金秋九月承载着抗战胜利70周年的喜庆扑面而来.没来得及任何准备,似乎也不需要任何准备,因为生活不需要太多将来时.每天忙着上班.加班.白加班,忘了去愤,忘了 ...

  7. MEF实现设计上的“松耦合”(三)

    1.面向接口编程:有一定编程经验的博友应该都熟悉或者了解这种编程思想,层和层之间通过接口依赖,下层不是直接给上层提供服务,而是定义一组接口供上层调用.至于具体的业务实现,那是开发中需要做的事情,在项目 ...

  8. Spring3系列2 -- 松耦合的实现

    Spring3系列2 -- 松耦合的实现 一.      环境 spring-framework-3.2.4.RELEASE jdk1.7.0_11 Maven3.0.5 eclipse-jee-ju ...

  9. Prism 4 文档 ---第9章 松耦合组件之间通信

    当构建一个大而负责的应用程序时,通用的做法时将功能拆分到离散的模块程序集中.将模块之间的静态引用最小化.这使得模块可以被独立的开发,测试,部署和升级,以及它迫使松散耦合的沟通. 当在模块之间通信时,你 ...

随机推荐

  1. Keepalived LVS-DR单网络双活双主配置模式

    Keepalived LVS-DR单网络双活双主配置模式 Linux就该这么学 今天 LVS是Linux Virtual Server的简写,意即Linux虚拟服务器,是一个虚拟的服务器集群系统.LV ...

  2. vue相关安装命令

    安装cnpm npm install cnpm -g --registry=https://registry.npm.taobao.org

  3. 转:CocoaPods pod install/pod update更新慢的问题

    最近使用CocoaPods来添加第三方类库,无论是执行pod install还是pod update都卡在了Analyzing dependencies不动 原因在于当执行以上两个命令的时候会升级Co ...

  4. layoutSubviews何时被调用

    layoutSubviews在以下情况下会被调用: 1.init初始化不会触发layoutSubviews 但是是用initWithFrame 进行初始化时,当rect的值不为CGRectZero时, ...

  5. C++持有Object-C对象时容易内存泄露

    在IOS项目中,可以将C++与Object-C混编,不过必须放在实现文件.mm中. 在.mm中,我们可能创建了一个C++对象A,而它持有一个Object-C对象B作为成员变量.当A对象被释放掉的时候, ...

  6. Shell记录-Shell脚本基础(六)

    watch是一个非常实用的命令,基本所有的Linux发行版都带有这个小工具,如同名字一样,watch可以帮你监测一个命令的运行结果,省得你一遍遍的手动运行. 1.命令格式 watch[参数][命令] ...

  7. bzoj千题计划129:bzoj2007: [Noi2010]海拔

    http://www.lydsy.com/JudgeOnline/problem.php?id=2007 1.所有点的高度一定在0~1之间, 如果有一个点的高度超过了1,那么必定会有人先上坡,再下坡, ...

  8. [HNOI 2013]切糕

    COGS 2398. [HNOI 2013]切糕 http://www.cogs.pro/cogs/problem/problem.php?pid=2398 ★★★☆   输入文件:nutcake.i ...

  9. How to Tell Science Stories with Maps

    Reported Features How to Tell Science Stories with Maps August 25, 2015   Greg Miller This map, part ...

  10. 织梦自定义表单通过ajax提交的实现方法

    自定义表单通过ajax判断,提交不用跳转页面,提高用户体验.具体方法如下: html表单代码部分,就提交按钮改成botton,,添加onclick事件 表单代码: <form action=&q ...