首先这里发一下结构图,因为是重写的,但是代码都是一样所有如下:

这里我先说一下看了大部分的DDD文章都是采用的WCF做服务,这里呢我用的是webapi做服务,WCF和WEBAPI的区别可以去百度下。

好了。现在我们看下automapper的具体实现。

因为automapper又一个Profile类,而我们自己写的类去继承这个类,所有如下图:

上图是创建映射关系,下面就去添加映射

这些做完了 我们现在需要使用

这里的dto类型是CostomDTO 也就是数据传输对象。

下面我们来看下工作单元,下面我直接贴代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace KuRuMi.Mio.DoMain.Repository.UnitOfWork
{
/// <summary>
/// 表示所有集成该接口都是工作单元的一种实现
/// </summary>
public interface IUnitOfWork
{
/// <summary>
/// 提交
/// </summary>
void Commit(); /// <summary>
/// 异步提交
/// </summary>
/// <returns></returns>
Task CommitSyncAsync(); /// <summary>
/// 回滚
/// </summary>
void Rollback(); /// <summary>
/// 已经提交过了
/// </summary>
bool Committed { get; } /// <summary>
/// 事务支持
/// </summary>
//bool DistributedTransactionSupported { get; }
}
}

这是IUnitOfWork接口代码。

using KuRuMi.Mio.DoMainModel.BaseModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace KuRuMi.Mio.DoMain.Repository.UnitOfWork
{
public interface IUnitOfWorkContext : IUnitOfWork, IDisposable
{
/// <summary>
/// 将指定的聚合根标注为“新建”状态。
/// </summary>
/// <typeparam name="TAggregateRoot">需要标注状态的聚合根类型。</typeparam>
/// <param name="obj">需要标注状态的聚合根。</param>
void RegisterNew<TAggregateRoot>(TAggregateRoot obj)
where TAggregateRoot : class, IAggregateRoot;
/// <summary>
/// 将指定的聚合根标注为“更改”状态。
/// </summary>
/// <typeparam name="TAggregateRoot">需要标注状态的聚合根类型。</typeparam>
/// <param name="obj">需要标注状态的聚合根。</param>
void RegisterModified<TAggregateRoot>(TAggregateRoot obj)
where TAggregateRoot : class, IAggregateRoot;
/// <summary>
/// 将指定的聚合根标注为“删除”状态。
/// </summary>
/// <typeparam name="TAggregateRoot">需要标注状态的聚合根类型。</typeparam>
/// <param name="obj">需要标注状态的聚合根。</param>
void RegisterDeleted<TAggregateRoot>(TAggregateRoot obj)
where TAggregateRoot : class, IAggregateRoot;
}
}

这是IUnitOfWorkContext接口代码

因为我是基于EF实现的所以这里多了一层EF的工作单元代码

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace KuRuMi.Mio.DoMain.Repository.UnitOfWork
{
/// <summary>
/// 表示是EF仓储的一种实现
/// </summary>
public interface IEFUnitOfWorkContext : IUnitOfWorkContext
{
DbContext Context { get; }
}
}

完成这里接下来就是工作单元的实现类

using KuRuMi.Mio.DoMainModel.BaseModel;
using KuRuMi.Mio.DoMain.Infrastructure;
using KuRuMi.Mio.DoMain.Repository.EFRepository;
using KuRuMi.Mio.DoMain.Repository.UnitOfWork;
using System.Data.Entity;
using System.Threading.Tasks; namespace KuRuMi.Mio.DoMain.Repository.BaseUnitOfWork
{
public class UnitOfWorkContext: DisposableObject, IEFUnitOfWorkContext
{
private KurumiMioDbContext kurumi = null; public UnitOfWorkContext() {
kurumi = new KurumiMioDbContext();
} public DbContext Context { get { return kurumi; } } #region 工作单元
public bool Committed { get; protected set; } /// <summary>
/// 同步提交
/// </summary>
public void Commit()
{
if (!Committed)
{
//kurumi.Value.GetValidationErrors();
Context.SaveChanges();
Committed = true;
}
} /// <summary>
/// 异步提交
/// </summary>
/// <returns></returns>
public async Task CommitSyncAsync()
{
if (!Committed)
{
await Context.SaveChangesAsync();
Committed = true;
}
}
/// <summary>
/// 释放资源
/// </summary>
/// <param name="disposing"></param>
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (!Committed)
Commit();
Context.Dispose();
kurumi.Dispose();
}
} /// <summary>
/// 回滚
/// </summary>
public void Rollback()
{
Committed = false;
}
#endregion #region IEFUnitOfWorkContext接口
/// <summary>
/// 删除未提交
/// </summary>
/// <typeparam name="TAggregateRoot"></typeparam>
/// <param name="obj"></param>
public void RegisterDeleted<TAggregateRoot>(TAggregateRoot obj) where TAggregateRoot : class, IAggregateRoot
{
Context.Entry(obj).State = EntityState.Deleted;
Committed = false;
} /// <summary>
/// 修改未提交
/// </summary>
/// <typeparam name="TAggregateRoot"></typeparam>
/// <param name="obj"></param>
public void RegisterModified<TAggregateRoot>(TAggregateRoot obj) where TAggregateRoot : class, IAggregateRoot
{
if (Context.Entry(obj).State == EntityState.Detached)
{
Context.Set<TAggregateRoot>().Attach(obj);
}
Context.Entry(obj).State = EntityState.Modified;
Committed = false;
} /// <summary>
/// 新建未提交
/// </summary>
/// <typeparam name="TAggregateRoot"></typeparam>
/// <param name="obj"></param>
public void RegisterNew<TAggregateRoot>(TAggregateRoot obj) where TAggregateRoot : class, IAggregateRoot
{
var state = Context.Entry(obj).State;
if (state == EntityState.Detached)
{
Context.Entry(obj).State = EntityState.Added;
}
Committed = false;
}
#endregion
}
}

现在呢就是我的仓储,因为是聚合根的缘故,所以聚合后的根有自己特有的仓储代码如下。

using KuRuMi.Mio.DoMainModel.Model;
using KuRuMi.Mio.DoMainModel.Repositories;
using KuRuMi.Mio.DoMain.Repository.EFRepository;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace KuRuMi.Mio.DoMain.Repository.ModelRepository
{
public class CostomRepositoryImpl :RepositoryImpl<Costom>, ICostomRepository
{
public KurumiMioDbContext context => lazy.Context as KurumiMioDbContext;
public Costom GetAll()
{
string sql = "select * from Costom";
return context.costom.SqlQuery(sql).FirstOrDefault();
}
}
}

然后是我的总仓储的实现

using KuRuMi.Mio.DoMainModel.BaseModel;
using KuRuMi.Mio.DoMainModel.Repositories;
using KuRuMi.Mio.DoMain.Repository.BaseUnitOfWork;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks; namespace KuRuMi.Mio.DoMain.Repository.EFRepository
{
/// <summary>
/// 仓储的泛型实现
/// </summary>
/// <typeparam name="TEntity"></typeparam>
public class RepositoryImpl<TEntity> : IRepository<TEntity> where TEntity : AggregateRoot
{
public readonly UnitOfWorkContext lazy = null;
public RepositoryImpl()
{
lazy = new UnitOfWorkContext(); } /// <summary>
/// 新增
/// </summary>
/// <param name="aggregateRoot"></param>
public virtual void Add(TEntity aggregateRoot)
{
lazy.RegisterNew<TEntity>(aggregateRoot);
lazy.Commit();
}
/// <summary>
/// 通过key获取聚合根
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public virtual TEntity GetKey(Guid key)
{
return lazy.Context.Set<TEntity>().Find(key);
} public virtual IQueryable<TEntity> LoadAll(Expression<Func<TEntity, bool>> predicate)
{
return lazy.Context.Set<TEntity>().Where(predicate).AsQueryable();
}
/// <summary>
/// 复杂查询
/// </summary>
/// <param name="sql"></param>
/// <returns></returns>
public virtual IQueryable<TEntity> LoadForSql(string sql)
{
return lazy.Context.Set<TEntity>().SqlQuery(sql).AsQueryable();
} public virtual IEnumerable<TEntity> LoadListAll(Expression<Func<TEntity, bool>> predicate)
{
return lazy.Context.Set<TEntity>().Where(predicate).ToList();
}
/// <summary>
/// 复杂查询
/// </summary>
/// <param name="sql"></param>
/// <returns></returns>
public virtual IEnumerable<TEntity> LoadListForSql(string sql)
{
return lazy.Context.Set<TEntity>().SqlQuery(sql).ToList();
} /// <summary>
/// 删除
/// </summary>
/// <param name="aggregateRoot"></param>
public virtual void Remove(TEntity aggregateRoot)
{
lazy.RegisterDeleted<TEntity>(aggregateRoot);
lazy.Commit();
} /// <summary>
/// 修改
/// </summary>
/// <param name="aggregateRoot"></param>
public virtual void Update(TEntity aggregateRoot)
{
lazy.RegisterModified<TEntity>(aggregateRoot);
lazy.Commit();
}
}
}

现在回到我们的服务层

系统初始化我采用的是autofac,至于为什么不采用unity,博主个人喜欢用autofac原因轻量,简单。

好了下面献上我的初始化系统类。

using KuRuMi.Mio.DataObject.AutoMapperDTO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using KuRuMi.Mio.DoMain.Infrastructure.IocManager;
using KuRuMi.Mio.DoMainModel.Repositories;
using Autofac; namespace KuRuMi.Mio.BootStarp
{ /// <summary>
/// 系统初始化
/// </summary>
public class OptionBootStarp
{
protected IEnumerable<Assembly> assembles { get; }
protected IIocManager ioc { get; }
public OptionBootStarp(IEnumerable<Assembly> ass)
{
assembles = ass;
ioc = IocManager.Instance;
}
protected IEnumerable<Type> Repository => assembles.SelectMany(a => a.ExportedTypes.Where(t => t.GetInterfaces().Contains(typeof(IBaseRepository))));
protected IEnumerable<Type> BaseDTO => assembles.SelectMany(a => a.ExportedTypes.Where(t => t.GetInterfaces().Contains(typeof(IAutoMapper)))); protected IEnumerable<Type> Services => assembles.SelectMany(a => a.ExportedTypes.Where(t => t.GetInterfaces().Contains(typeof(IService))));
/// <summary>
/// 预加载
/// </summary>
public void Initialize()
{
//加载所有DTO
BaseDTO.ToList().ForEach(s=> {
var dtpye= Activator.CreateInstance(s) as IAutoMapper;
ioc.build.RegisterInstance(dtpye).As<MapperConfigurationImpl>().SingleInstance().PropertiesAutowired();
});
//加载所有的仓储
Repository.ToList().ForEach(s => {
if (s.IsClass == true && s.IsGenericType == false)
{
var dtpye = Activator.CreateInstance(s);
ioc.build.RegisterType(dtpye.GetType()).As(dtpye.GetType());
}
});
//加载所有服务
Services.ToList().ForEach(s =>
{
if (s.IsClass == true)
{
var stype = Activator.CreateInstance(s);
ioc.build.RegisterType(stype.GetType()).As(stype.GetType());
}
});
PostInit();
}
/// <summary>
/// 注入
/// </summary>
protected void PostInit() {
ioc.CompleteBuild();
}
} }

下面贴上测试结果,WEB端请求的是webapi其中涉及到跨域请求问题,采用的是微软的cors包。

需要代码的同学点这里。

PS:采用了autofac IOC框架 automapper 映射框架 Log4Net 日志 ORM是EF 用的是codefirst 运行的时候只需要改web.config的数据库连接就可以了。

链接: 百度 密码: 3baw

DDD领域驱动之干货(三)完结篇!的更多相关文章

  1. DDD领域驱动之干货(四)补充篇!

    距离上一篇DDD系列完结已经过了很长一段时间,项目也搁置了一段时间,想想还是继续完善下去. DDD领域驱动之干货(三)完结篇! 上一篇说到了如何实现uow配合Repository在autofac和au ...

  2. DDD 领域驱动设计-三个问题思考实体和值对象(续)

    上一篇:DDD 领域驱动设计-三个问题思考实体和值对象 说实话,整理现在这一篇博文的想法,在上一篇发布出来的时候就有了,但到现在才动起笔来,而且写之前又反复读了上一篇博文的内容及评论,然后去收集资料, ...

  3. DDD 领域驱动设计-三个问题思考实体和值对象

    消息场景:用户 A 发送一个消息给用户 B,用户 B 回复一个消息给用户 A... 现有设计:消息设计为实体并为聚合根,发件人.收件人设计为值对象. 三个问题: 实体最重要的特性是什么? Messag ...

  4. [转] DDD领域驱动设计(三) 之 理论知识收集汇总

    最近一直在学习领域驱动设计(DDD)的理论知识,从网上搜集了一些个人认为比较有价值的东西,贴出来和大家分享一下: 我一直觉得不要盲目相信权威,比如不能一谈起领域驱动设计,就一定认为国外的那个Eric ...

  5. DDD领域驱动之干货 (一)

    说道DDD不得不说传统的架构与DDD的架构区别. 传统的架构不外乎就是三层,而在这三层里面又不断的细分,始终没有达到想要的效果,那么为什么当时还是采用三层. 当然在DDD没有提出的时候三层是大多数人的 ...

  6. DDD领域驱动之干货(二)

       基于仓储的实现 1.前言:本着第一节写的有些糊涂,主要是自己喜欢实干,不太喜欢用文字表述,就这样吧.下面切入正题. 博客园里面有很多的大佬,我这里就不一一解释概览,有兴趣的朋友可以去看大佬们写的 ...

  7. [0] DDD领域驱动设计(三) 之 聚合(根)、实体、值对象

    1.      聚合根.实体.值对象的区别? 从标识的角度: 聚合根具有全局的唯一标识,而实体只有在聚合内部有唯一的本地标识,值对象没有唯一标识,不存在这个值对象或那个值对象的说法: 从是否只读的角度 ...

  8. DDD领域驱动之干活(四)补充篇!

    距离上一篇DDD系列完结已经过了很长一段时间,项目也搁置了一段时间,想想还是继续完善下去. DDD领域驱动之干货(三)完结篇! 上一篇说到了如何实现uow配合Repository在autofac和au ...

  9. DDD 领域驱动设计-“臆想”中的实体和值对象

    其他博文: DDD 领域驱动设计-三个问题思考实体和值对象 DDD 领域驱动设计-三个问题思考实体和值对象(续) 以下内容属于博主"臆想",如有不当,请别当真. 扯淡开始: 诺兰的 ...

随机推荐

  1. 伸展树(Splay树)的简要操作

    伸展树(splay树),是二叉排序树的一种.[两个月之前写过,今天突然想写个博客...] 伸展树和一般的二叉排序树不同的是,在每次执行完插入.查询.删除等操作后,都会自动平衡这棵树.(说是自动,也就是 ...

  2. C#设计模式之简单工厂模式

    简单工厂模式解释:  简单工厂模式(Simple Factory Pattern)属于类的创新型模式,又叫静态工厂方法模式(Static FactoryMethod Pattern) 是通过专门定义一 ...

  3. flowJS源码个人分析

    刚刚在腾讯云技术社区前端专栏中看到一篇腾讯高级前端工程师写的<一个只有99行代码的js流程框架>觉得很屌,感觉是将后台的简单的工作流思维搬到了前端js实现,本人不才在这里拜读解析下源码,而 ...

  4. 找到一个新的超好用的U盘启动制作工具了

    有同事叫帮装电脑,弄个U盘说制作一个启动盘,结果一搜,出了“雨林木风”的主页. 太好用了,高手的产物,比以前找的方便一百倍.又简单,又实用,同步又下载好GHO文件.唯一 的问题是XP中用的GHO,好多 ...

  5. 给 endv 取个好名字有赏!

    给 endv 取个好名字有赏! 直接回复即可 给 endv 取个好名字,拆分原则 endv = endv endv = end+v endv = en+d+v endv = en+dv endv = ...

  6. redis 链表

    redis 链表 前言 借鉴了 黄健宏 的 <<Redis 设计与实现>> 一书, 对 redis 源码进行学习 欢迎大家给予意见, 互相沟通学习 概述 redis 的链表结构 ...

  7. Google Chrome 默认非安全端口列表

    1, // tcpmux7, // echo 9, // discard 11, // systat 13, // daytime 15, // netstat 17, // qotd 19, // ...

  8. ADO.NET 获取SQL SERVER数据库架构信息

    1.确定可用字段数目 sqlDataReader类提供了FieldCount属性,可确定查询反悔了多少个字段. 2.确定返回行的数目 sqlDataReader中没有指示可用行的属性. 3.确定字段的 ...

  9. [进程管理]linux 下 进程和线程的区别(baidu 面试)

    进程是程序执行时的一个实例,即它是程序已经执行到课中程度的数据结构的汇集.从内核的观点看,进程的目的就是担当分配系统资源(CPU时间.内存等)的基本单位. 线程是进程的一个执行流,是CPU调度和分派的 ...

  10. 人生苦短,我用Python

    Life is short, You need Python. 工作中常常要用到脚本来完成许多重复性的工作,刚开始是查数据库的时候,也曾用shell 来写脚本,但终于还是觉得shell太艰涩, 一行命 ...