首先這里發一下結構圖,因為是重寫的,但是代碼都是一樣所有如下:
這里我先說一下看了大部分的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