最近看了NopCommerce源码,用core学习着写了一个项目,修改的地方记录下。项目地址
NopCommerce框架出来好久了。18年的第一季度 懒加载出来后也会全部移动到.net core。那么就更好玩了。
项目内容
- 模仿部分
- 分层模式
- 引擎机制
- DI容器
- EF
- 仓储模式
- Mapping
- 部分修改
- .net core 重写类库
- EFcore mysql 动态加载dbset
当然NopCommerce还包含很多特技:Plugin,Seo,订阅发布,theme切换等等。这些后期再维护进去。
项目介绍
- 项目分层
- 1、Libraries
Nop.Core:【核心层】基础设施,例:领域对象,仓库接口,引擎接口,DI管理接口,反射,公共方法。
Nop.Data:【数据层】EF相关,dbcontext,仓储实现,mapping
Nop.Services:【服务层】数据逻辑处理由这层提供。
- 2、Presentation
Nop.Web:【页面层】展示界面。
Nop.Web.Framework:【页面基础层】web层的上层封装。例如启动项的实现,DI实现。
详细的分层思想和细节这里不再复述。
2.项目修改点
EF6转换到EFCore,数据库选择mysql,动态加载dbset 看了相关代码,在进行解释
1 public class DataBaseStartup: ISelfStartup 2 { 3 4 public void ConfigureServices(IServiceCollection services, IConfigurationRoot configuration) 5 { 6 services.AddDbContext<SelfDbContext>(x => x.UseMySql(configuration.GetConnectionString("MySql"))); 7 } 8 9 public void Configure(IApplicationBuilder application) 10 { 11 var dbContext=EngineContext.Current.ServiceProvider.GetService<SelfDbContext>(); 12 dbContext.Database.EnsureCreated(); 13 } 14 15 public int Order { get; } = 1; 16 }
public SelfDbContext(DbContextOptions options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.AddEntityConfigurationsFromAssembly(GetType().Assembly); base.OnModelCreating(modelBuilder); }
1 public static class ModelBuilderExtenions 2 { 3 private static IEnumerable<Type> GetMappingTypes(this Assembly assembly, Type mappingInterface) 4 { 5 return assembly.GetTypes().Where(x => !x.IsAbstract && !x.IsGenericType && !x.IsInterface && x.GetInterfaces().Any(y => y == mappingInterface)); 6 } 7 8 public static void AddEntityConfigurationsFromAssembly(this ModelBuilder modelBuilder, Assembly assembly) 9 { 10 var mappingTypes = assembly.GetMappingTypes(typeof(ISelfEntityMappingConfiguration)); 11 foreach (var config in mappingTypes.Select(Activator.CreateInstance).Cast<ISelfEntityMappingConfiguration>()) 12 { 13 config.Map(modelBuilder); 14 } 15 } 16 }
1 public class StudentMapping : ISelfEntityMappingConfiguration 2 { 3 public void Map(ModelBuilder b) 4 { 5 b.Entity<Student>().ToTable("Student") 6 .HasKey(p => p.Id); 7 8 b.Entity<Student>().Property(p => p.Class).HasMaxLength(50).IsRequired(); 9 b.Entity<Student>().Property(p => p.Name).HasMaxLength(50); 10 } 11 }
1 public interface ISelfEntityMappingConfiguration 2 { 3 void Map(ModelBuilder b); 4 }
1 public class Student:BaseEntity 2 { 3 public string Name { get; set; } 4 5 public string Class { get; set; } 6 }
解释:
- DataBaseStartup是继承Startup的数据中间件处理类。这里去选择数据库类型和dbcontext,以及数据库初始化。Nopcommerce原先是在install那层判断是否存在数据库json处理数据库初始化,这里简单化了,初始化可以抽象出来再处理。这个类的实现是在web.framwork层。解耦了核心与web层的。这里完全可以自己再重写一个处理类,用来切换数据库等其他操作。
- SelfDbContext是数据处理上下文类。以前写的dbcontext处理新增的实体类dbset都是一个一个属性添加,这里是通过反射进行动态加载。相关的方法写在了modelbuilder的扩展方法里面
- ModelBuilderExtenions是modelbuilder的构建扩展方法的类。里面介绍如何通过反射查找如要map进入的实体map对象。主要通过对比类型继承的接口对象type
- ISelfEntityMappingConfiguration是所有map对象的上层接口,通过这个类的类别判断实体加入到dbcontext
- StudentMapping和student类是这里举例的例子。Mapping可以对数据字段进行处理。当然也可以直接在实体类加上attribute。
3.项目继承nopcommerce的其他地方
- 引擎构建。项目中也构建了EngineContext和IEngine。引擎是整个项目启动的处理核心,处理的东西不再复述。发现构建了这个之后 可以切换orm框架了。对于一些大型需要对接第三方同步orm,那么这个构建出来之后就非常好处理了。当然好处的地方还有更多。
- 仓储模式。这里其实是伪仓储,封装多出一个仓库管理员,并没有事务聚合根等做法。
- DI选择auotofac。
- 引擎构建。项目中也构建了EngineContext和IEngine。引擎是整个项目启动的处理核心,处理的东西不再复述。发现构建了这个之后 可以切换orm框架了。对于一些大型需要对接第三方同步orm,那么这个构建出来之后就非常好处理了。当然好处的地方还有更多。