• DDD模块


     context.Services.AddSingleton(typeof(IDataFilter<>), typeof(DataFilter<>));

    模块的依赖模块

     [DependsOn(
            typeof(AbpAuditingModule),
            typeof(AbpDataModule),
            typeof(AbpEventBusModule),
            typeof(AbpGuidsModule),
            typeof(AbpMultiTenancyModule),
            typeof(AbpThreadingModule),
            typeof(AbpTimingModule),
            typeof(AbpUnitOfWorkModule),
            typeof(AbpObjectMappingModule)
            )]
        public class AbpDddDomainModule : AbpModule
        {
    
        }

     1、实体

        Defines an entity. It's primary key may not be "Id" or it may have a composite primary key.  

       object[] GetKeys();

      在 IEntity<TKey> 的默认实现 Entity<TKey> 中,不仅提供了标识定义,也重写了 Equals() 比较方法和 ==  != 操作符,用于区别不同实体

       1)聚合根

    聚合就是一组相关对象的集合,他会有一个根对象(root),和它的一个边界(boundary)。对于聚合外部来说,只能够引用它的根对象,而在聚合内部的其他对象则可以相互引用。

    该类型也继承自 Entity 类型,并且内部提供了一个并发令牌防止并发冲突。并且在其内部也提供了领域事件的快速增删方法,其他的与常规实体基本一致。通过领域事件,我们可以完成对事务的拆分。例如上述的例子当中,我们也可以为 Part 增加一个领域事件,当价格被更新时,PO 可以订阅这个事件,实现对应的采购项更新。

        [Serializable]
        public abstract class AggregateRoot<TKey> : Entity<TKey>, 
            IAggregateRoot<TKey>, 
            IGeneratesDomainEvents, 
            IHasExtraProperties,
            IHasConcurrencyStamp
        public interface IGeneratesDomainEvents
        {
            IEnumerable<object> GetLocalEvents();
    
            IEnumerable<object> GetDistributedEvents();
    
            void ClearLocalEvents();
    
            void ClearDistributedEvents();
        }

    什么是审计属性呢?在 ABP vNext 内部将以下属性定义为审计属性:创建人创建时间修改人修改时间删除人删除时间软删除标记

    2)AuditedAggregateRootWithUser<TUser> 携带User的class类  public virtual TUser Creator { get; set; }

    Audited和FullAudit的区别:

    audited包括Creation,Modification的相关信息,

    而FullAudit除了audited信息,还包括了IsDeleted,DeleterId,DeletionTime等软删除信息

    3)事件

      public class EntityEventData<TEntity> : IEventDataWithInheritableGenericArgument

     DomainEventEntry

    2、仓储

    IReadOnlyBasicRepository<TEntity> ;包括GetList(),GetCount()

    IReadOnlyBasicRepository<TEntity, TKey>; 增加Gets an entity with given primary key

    IBasicRepository<TEntity, TKey>;在IReadOnlyBasicRespository基础上增加Insert,Update,Delete

    IRepository是在增加表达式树,并且包括IReadOnlyBasicRepository, IBasicRepository

    public interface IRepository<TEntity, TKey> : IRepository<TEntity>, 
    IReadOnlyRepository<TEntity, TKey>, IBasicRepository<TEntity, TKey> where TEntity : class, IEntity<TKey> { }

    RepositoryBase比BasicRepositoryBase,增加IDataFilter,ICurrentTenant,IQueryable

        public abstract class RepositoryBase<TEntity> : BasicRepositoryBase<TEntity>, IRepository<TEntity>
            where TEntity : class, IEntity

    AbpDataFilterOptions:设置每个类型的数据筛选状态是否启用

    IDataFilter<TFilter>,在模块的ConfigureServices已注入Singleton模式,获取当前类型是否数据筛选状态,为了保证每一个类型可以得到值 ,首先来源AbpDataFilterOptions,若存在,克隆一个,若不存在则设置为true

    DataFilter,IDataFilter自动注册Singleton到容器里,往容器取出IDataFilter<TFilter>进行Enable、Disable,若第一次增加到自身集合,方便下次操作

    抽象方法RepositoryRegistrarBase,仓储的具体实现模块都实现了这个基类

    实现有EfCoreRepositoryRegistrar;MemoryDbRepositoryRegistrar;MongoDbRepositoryRegistrar

    仓储肯定会有多种实现的,例如 EF Core 的仓储实现肯定有自己的一套注册机制,

    3、服务

    IDomainService,DomainService

    4、值对象 ValueObject

    并且按照聚合的特性来说,其实聚合与聚合之间的通讯,主要是通过领域事件来实现的。

     

    调用 ApiDescriptionModelOptions ,往里面添加了 IRemoteServiceIApplicationServiceIUnitOfWOrkEnabled 三种接口类型。添加了三种类型之后,ABP vNext 根据应用服务类创建控制器时,就会从这个 IgnoredInterfaces 判断哪些类型不被忽略 (即只会自动注册实现了三种接口的类型成为控制器)。

    [DependsOn(
            typeof(AbpDddDomainModule),
            typeof(AbpSecurityModule),
            typeof(AbpObjectMappingModule),
            typeof(AbpValidationModule),
            typeof(AbpAuthorizationModule),
            typeof(AbpHttpAbstractionsModule),
            typeof(AbpSe、ttingsModule),
            typeof(AbpFeaturesModule)
            )]
        public class AbpDddApplicationModule : AbpModule
        {
            public override void ConfigureServices(ServiceConfigurationContext context)
            {
                Configure<ApiDescriptionModelOptions>(options =>
                {
                    options.IgnoredInterfaces.AddIfNotContains(typeof(IRemoteService));
                    options.IgnoredInterfaces.AddIfNotContains(typeof(IApplicationService));
                    options.IgnoredInterfaces.AddIfNotContains(typeof(IUnitOfWorkEnabled));
                });
            }
        }

    1、Dtos

    请求

    ILimitedResultRequest  =》  int MaxResultCount { get; set; }

    ISortedResultRequest=》string Sorting { get; set; }  比如 "Name";"Name DESC";"Name ASC, Age DESC"

    IPagedResultRequest=》包括ILimitedResultRequest; int SkipCount { get; set; }  Skip count (beginning of the page).

    IPagedAndSortedResultRequest=》 IPagedResultRequest, ISortedResultRequest

    返回结果

    TKey Id { get; set; }

    IHasTotalCount =》  long TotalCount { get; set; } 

    IListResult<T>  =》  IReadOnlyList<T> Items { get; set; }

    IPagedResult<T> 包含 IListResult<T>, IHasTotalCount

    实体

    顺序:IEntityDto 》 CreationAuditedEntityDto 、CreationAuditedEntityWithUserDto》AuditedEntityDto、AuditedEntityWithUserDto<TUserDto>

    =》FullAuditedEntityDto、FullAuditedEntityWithUserDto

    2、Services

    IRemoteService=》IApplicationService

    所有应用服务都必须继承 IApplicationService,这个是肯定的,不然 ABP vNext 不会为我们生成需要的控制器。

    public abstract class ApplicationService :
            IApplicationService,
            IAvoidDuplicateCrossCuttingConcerns,
            IValidationEnabled,
            IUnitOfWorkEnabled,
            IAuditingEnabled,
            ITransientDependency
        {

    IAvoidDuplicateCrossCuttingConcerns 接口,它的主要作用是防止拦截器进行重复执行。

      public interface IAvoidDuplicateCrossCuttingConcerns
        {
            List<string> AppliedCrossCuttingConcerns { get; }
        }

    例如调用购买这个 API 接口,首先会进入 ASP.NET Core 的审计日志 Filter,在 Filter 里面会将这个 API 接口归属的类型的 List 容器(接口里面定义的 List )里面写入一条记录,说明已经通过审计日志过滤器记录了。

    写了审计日志之后,又会进入审计日志拦截器,这个时候拦截器就会对指定的类型进行判断,看是否已经被执行过了,因为这个类型的 List 容器有了之前过滤器的记录,所以不会重复执行。

            public static bool IsApplied([NotNull] object obj, [NotNull] string concern)
            {
                if (obj == null)
                {
                    throw new ArgumentNullException(nameof(obj));
                }
    
                if (concern == null)
                {
                    throw new ArgumentNullException(nameof(concern));
                }
    
                return (obj as IAvoidDuplicateCrossCuttingConcerns)?.AppliedCrossCuttingConcerns.Contains(concern) ?? false;
            }

     剩余的 IValidationEnabledIUnitOfWorkEnabledIAuditingEnabledITransientDependency 接口类似于一个启用标识,只要类型继承了该接口,就会执行一些特殊的操作。

    基类,注入大量基础设施,比如IUnitOfWorkManager、 IObjectMapper、IGuidGenerator、ILoggerFactory、ILogger、ICurrentTenant、ICurrentUser、ISettingProvider、IClock

    IAuthorizationService、IFeatureChecker、IStringLocalizer

     public interface IAsyncCrudAppService<TEntityDto, in TKey, in TGetListInput, in TCreateInput, in TUpdateInput>
            : IApplicationService
            where TEntityDto : IEntityDto<TKey>
        {
            Task<TEntityDto> GetAsync(TKey id);
    
            Task<PagedResultDto<TEntityDto>> GetListAsync(TGetListInput input);
    
            Task<TEntityDto> CreateAsync(TCreateInput input);
    
            Task<TEntityDto> UpdateAsync(TKey id, TUpdateInput input);
    
            Task DeleteAsync(TKey id);
        }
  • 相关阅读:
    final
    职场语句
    故事
    三个关键字
    关于重读字母去掉的代码
    Java书
    docker私库harbor的搭建
    配置允许匿名用户登录访问vsftpd服务,进行文档的上传下载、文档的新建删除等操作
    docker容器内外相互拷贝数据
    docker
  • 原文地址:https://www.cnblogs.com/cloudsu/p/11190697.html
Copyright © 2020-2023  润新知