怎样做php网站,网站建设方案ppt下载,wordpress建站云盘,杨谦教授编的营销课程一、充血模型和失血模型1. 充血模型的优势充血模型更加OOP充血模型代码可读性更好1.1 充血模型伪代码var messageDto controller.ReadDto();var message messageDto.ToEntity();message.Save();1.2 失血模型伪代码var messageDto controller.ReadDto();var message message…一、充血模型和失血模型1. 充血模型的优势充血模型更加OOP充血模型代码可读性更好1.1 充血模型伪代码var messageDto controller.ReadDto();var message messageDto.ToEntity();message.Save();1.2 失血模型伪代码var messageDto controller.ReadDto();var message messageDto.ToEntity();var messageService controller.GetMessageService();messageService.Save(message);2. 充血模型爱你不容易大部分程序员都知道充血模型好,想实现却很难大部分业务逻辑都需要依赖外部服务充血模型需要用到外部服务,又不想依赖外部服务的具体实现很容易想到使用IOC的依赖注入来解决我们给DTO注入服务还行,因为IOC参与了controller过程当DTO发生转化时,新增的服务IOC还是有点力不从心没法引用外部服务的充血模型气血不通,业务表达能力大大下降这也是大部分人弃用充血模型的主要原因,不好用还不如不用这个任督二脉PocoEmit可以帮你打通二、首先来个Case演示一下Dto转化为实体但是实体有更多逻辑依赖外部服务,这些外部服务Dto不见得提供的了这就需要注入PocoEmit支持构造函数参数注入和属性注入IMapper对象是默认支持注入的服务1. Entity比Dto多出来的Mapper可以注入class MessageDto{public string Message { get; set; }}class MessageEntity{public IMapper Mapper { get; set; }public string Message { get; set; }}2. 转化并注入的代码var mapper Mapper.Create();var dto new MessageDto { Message Hello UseMapper };MessageEntity message mapper.ConvertMessageDto, MessageEntity(dto);Assert.NotNull(message.Mapper);三、再演示注入自定义的服务1. UserDomain比Dto多出来的Repository可以注入class UserDTO{public int Id { get; set; }public string Name { get; set; }}class UserDomain(UserRepository repository, int id, string name){private readonly UserRepository _repository repository;public UserRepository Repository _repository;public int Id { get; } id;public string Name { get; } name;// ...}class UserRepository{void Add(UserDomain user) { }void Update(UserDomain entity) { }void Remove(UserDomain entity) { }public static readonly UserRepository Instance new();}2. 注册、转化并注入的代码通过UseDefault可以注入服务IMapper mapper Mapper.Create().UseDefault(UserRepository.Instance);var dto new UserDTO { Id 1, Name Jxj };UserDomain user mapper.ConvertUserDTO, UserDomain(dto);Assert.NotNull(user.Repository);四、注入IOC容器的Case注入IOC容器需要安装nuget包PocoEmit.ServiceProvider1. 包含IOC容器的实体class UserWithServiceProvider{public int Id { get; set; }public string Name { get; set; }public IServiceProvider ServiceProvider { get; set; }}2. 注册、转化并注入的代码UseSingleton是把容器作为唯一容器注入UseScope是使用当前Scope子容器UseContext是在Mvc下,使用当前HttpContext的RequestServices子容器var services new ServiceCollection();var serviceProvider services.BuildServiceProvider();var mapper Mapper.Create();mapper.UseSingleton(serviceProvider);var dto new UserDTO { Id 1, Name Jxj };UserWithServiceProvider user mapper.ConvertUserDTO, UserWithServiceProvider(dto);Assert.NotNull(user.ServiceProvider);五、当然还可以注入容器内的服务1. UserDomain多出来的Repository需要注入这次我们用IOC来管理Repository这样才能更好的利用依赖注入Repository可能还会依赖其他的服务手动维护服务对象可能会很麻烦,IOC容器擅长维护这些复杂关系class UserDomain(UserRepository repository, int id, string name){private readonly UserRepository _repository repository;public UserRepository Repository _repository;public int Id { get; } id;public string Name { get; } name;// ...}class UserRepository{void Add(UserDomain user) { }void Update(UserDomain entity) { }void Remove(UserDomain entity) { }}2. 注册、转化并注入的代码通过UseScope注入IOC容器通过UseDefault告知这个类型从IOC容器中注入var services new ServiceCollection().AddScopedUserRepository();var serviceProvider services.BuildServiceProvider();var mapper Mapper.Create();mapper.UseScope(serviceProvider).UseDefaultUserRepository();var dto new UserDTO { Id 1, Name Jxj };UserDomain user mapper.ConvertUserDTO, UserDomain(dto);Assert.NotNull(user.Repository);六、支持IOC容器的特性支持FromKeyedServices支持FromServices1. FromKeyedServices标记注入点和服务键class UserDomain1([FromKeyedServices(User1)]UserRepository repository, int id, string name): UserDomain(repository, id, name){}class UserDomain2([FromKeyedServices(User2)] UserRepository repository, int id, string name): UserDomain(repository, id, name){}class UserDomain(UserRepository repository, int id, string name){private readonly UserRepository _repository repository;public UserRepository Repository _repository;public int Id { get; } id;public string Name { get; } name;// ...}class UserRepository(string tableName){private readonly string _tableName tableName;public string TableName _tableName;void Add(UserDomain user) { }void Update(UserDomain entity) { }void Remove(UserDomain entity) { }}2. 注册、转化并注入的代码由于识别出FromKeyedServices,就不需要UseDefault这样简洁又优雅string table1 User1;string table2 User2;var services new ServiceCollection().AddKeyedScoped(table1, (_, _) new UserRepository(table1)).AddKeyedScoped(table2, (_, _) new UserRepository(table2));var serviceProvider services.BuildServiceProvider();var mapper Mapper.Create();mapper.UseScope(serviceProvider);var dto new UserDTO { Id 1, Name Jxj };UserDomain user mapper.ConvertUserDTO, UserDomain1(dto);Assert.NotNull(user.Repository);UserDomain user2 mapper.ConvertUserDTO, UserDomain2(dto);Assert.NotNull(user2.Repository);七、竞品类似的功能1. AutoMapper不支持AutoMapper的NullSubstitute用来指定源属性为null时的默认值用AutoMapper实现类似功能需要复杂的自定义IValueResolver来实现PocoEmit在源无法匹配或源字段为null都可能触发依赖注入2. EF有类似功能不过貌似只支持EF内部某些服务请参阅 EF Core实体类的依赖注入八、总结1. OOM映射需要依赖注入DTO、实体、领域模型如果有业务逻辑就需要依赖外部服务支持按类型注入,也支持按指定的参数或属性注入支持FromKeyedServices和FromServices需要外部服务就需要依赖注入2. PocoEmit的依赖注入助力程序分层架构依赖注入的加持每一层想调用啥就调用啥同时也让每一层更好的划分让调用啥,不让调用啥更容易控制同时也让业务需要划分多少层就划分多层变得简单3. IOC容器使用需要注意简单作业单容器,使用UseSingleton即可多线程需要使用UseScopeMvc(含WebApi)逻辑处理使用UseContextUseContext需要引用nuget包PocoEmit.Mvc如果是Mvc异步处理或Quartz类似作业不要用UseContext就怕异步中获取到了HttpContext,但执行中途被释放了,后面就可能异常了