[Abp vNext source code analysis] - the application layer support 6. DDD (application service)

First, a brief introduction

ABP vNext for the application service layer, be implemented as we designed a single module that Volo.Abp.Ddd.Application module.

PS: Recently bloggers also cramming DDD in relevant knowledge, here we recommend a look at ThoughtWorks the DDD related articles.

About DDD related books, I recommend here that three classic "domain-driven design: the core software complexity response to it," "achieve Domain Driven Design", "Domain Driven Design essence" .

Overall, DDD is more boring learning, and the theory of partial knowledge. Examples of binding it is necessary to look at a large number of repeated control better understanding of the concept of the book. Not only look at examples of other people, you also have to try to apply a strategic approach and tactical methods of DDD design.

DDD application service layer in a layered architecture which is the top, usually dealing with the front end (presentation layer) are application service layer. Conventional developers, if not followed DDD theory to be developed, then the application service layer is very bloated, which are all business logic. Field of the layer which is empty, full field model objects anemia. This model is called the model field mode anemia , which is a counter-pattern .

I will not repeat here the relationship between the service layer and application of the DDD, where you can be seen as it is an API interface classes, all interfaces are you opening up through the application service layer exposed interface methods should It corresponds with the embodiment.

Second, source code analysis

Application service layer module which is relatively simple, only two folders are stored the data transfer model (DTOS) base class definition and application services (Services).

2.1 Start Module

First we follow the previous sequence, look at his watch a module module class. Here we look at the AbpDddApplicationModulecode.

[DependsOn(
    typeof(AbpDddDomainModule),
    typeof(AbpSecurityModule),
    typeof(AbpObjectMappingModule),
    typeof(AbpValidationModule),
    typeof(AbpAuthorizationModule),
    typeof(AbpHttpAbstractionsModule),
    typeof(AbpSettingsModule),
    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));
        });
    }
}

It can be seen in the above code inside, only one thing is to call ApiDescriptionModelOptions, I entered, added IRemoteService, IApplicationService, IUnitOfWOrkEnabledthree interface types. With the addition of three types, ABP vNext according to the application service class to create a controller, this will be IgnoredInterfaceswhat type of judgment will not be ignored (ie, only registered automatically implements three types of interfaces become controller).

2.2 base class application services

ABP vNext provides a standard base class ApplicationServiceand a simple Crud base class CrudAppServicefor our use, but the former inherited IApplicationServiceinterface, and provides a simple base class basic components. While the latter is defined API method Crud all operations needed, you only need to extend this base class object, populate the generic parameters, can quickly implement a Crud interface.

2.2.1 simple base class

Simple base class first thing we need to note that it implements an interface, you can find ApplicationServiceimplement many interfaces, but these interfaces are more similar to the interface identifier.

public abstract class ApplicationService :
    IApplicationService,
    IAvoidDuplicateCrossCuttingConcerns,
    IValidationEnabled,
    IUnitOfWorkEnabled,
    IAuditingEnabled,
    ITransientDependency
{
    // ... 其他代码
}

All apps must be inherited IApplicationService, this is certain, otherwise ABP vNext controller need not be generated for us.

Followed by the IAvoidDuplicateCrossCuttingConcernsinterface, which dates back to the old version of ABP frame inside. Its main role is to prevent the interceptor be repeated.

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

For example, buy call this API interface, will first enter ASP.NET Core Filter audit log, which will in Filter this type of API interface belongs Listwrites a record container (List interfaces defined inside) inside, explanation has been through the audit log filter records.

After writing the audit log, audit log will enter the interceptor, this time the interceptor will specify the type of judge to see if has been executed, because this type of Listcontainer has been previously recorded filter, it is not It will be repeated.

public override void Intercept(IAbpMethodInvocation invocation)
{
    if (!ShouldIntercept(invocation, out var auditLog, out var auditLogAction))
    {
        invocation.Proceed();
        return;
    }

    // ... 审计日志记录。
}

protected virtual bool ShouldIntercept(
    IAbpMethodInvocation invocation, 
    out AuditLogInfo auditLog, 
    out AuditLogActionInfo auditLogAction)
{
    // 判断实例的 List 容器里面,是否写入了 AbpCrossCuttingConcerns.Auditing。
    if (AbpCrossCuttingConcerns.IsApplied(invocation.TargetObject, AbpCrossCuttingConcerns.Auditing))
    {
        return false;
    }
    
    // ... 其他代码

    return true;
}

The remaining IValidationEnabled, IUnitOfWorkEnabled, IAuditingEnabled, ITransientDependencyinterface is similar to a logo enabled, as long as the inherited type of this interface will perform some special operations.

Before the return to simple base class, ABP vNext for us to inject a lot of infrastructure, such as access to the user's current ICurrentUsercomponents, to get the current tenant of the ICurrentTenantcomponents, as well as logging components.

In addition to basic components, ABP vNext simple base class also provides a method for detecting permission, the user detects whether the current user is provided with certain privileges.

protected virtual async Task CheckPolicyAsync([CanBeNull] string policyName)
{
    if (string.IsNullOrEmpty(policyName))
    {
        return;
    }

    await AuthorizationService.CheckAsync(policyName);
}

When we do not have the authority, ABP vNext will throw AbpAuthorizationExceptionan exception.

2.2.2 Crud base class

Crud base class can greatly reduce the code for some simple objects to write, for example, I have a client management interface, simply CRUD operations. After then I can Crud directly inherited from the base class, and to fill it are generic parameters, ABP vNext will generate for our clients with the additions and deletions to change search application operation.

The Crud base class has more generic definition and implementation, in addition to the real implementation, others are simply just call the base class method. We go directly to the topic, look at the type signature public abstract class CrudAppService<TEntity, TGetOutputDto, TGetListOutputDto, TKey, TGetListInput, TCreateInput, TUpdateInput>of the base class.

public abstract class CrudAppService<TEntity, TGetOutputDto, TGetListOutputDto, TKey, TGetListInput, TCreateInput, TUpdateInput>
   : ApplicationService,
    ICrudAppService<TGetOutputDto, TGetListOutputDto, TKey, TGetListInput, TCreateInput, TUpdateInput>
    where TEntity : class, IEntity<TKey>
    where TGetOutputDto : IEntityDto<TKey>
    where TGetListOutputDto : IEntityDto<TKey>
{
    public virtual async Task<TGetOutputDto> GetAsync(TKey id)
    {
        // 具体代码。
    }
    
    public virtual async Task<PagedResultDto<TGetListOutputDto>> GetListAsync(TGetListInput input)
    {
        // 具体代码。
    }
    
    public virtual async Task<TGetOutputDto> CreateAsync(TCreateInput input)
    {
        // 具体代码。
    }
    
    public virtual async Task<TGetOutputDto> UpdateAsync(TKey id, TUpdateInput input)
    {
        // 具体代码。
    }
    
    public virtual async Task DeleteAsync(TKey id)
    {
        // 具体代码。
    }
}

The code can be seen from the above base class in accordance with the generic parameter passed, it will be achieved for the conventional additions and deletions we change search logic. We can always override these methods to achieve some of the personalized operation.

ABP vNext abstract public interface outside, inside also wrote such MapToEntity()and MapToEntity()internal common methods here will not go into detail, these methods are protectedmodified, you can always rewrite to achieve their own ends.

2.3 Data Transfer Object

In general, application service layer returns to the data presentation layer is certainly part of the property of an entity object, or multiple aggregated overall, this time need DTO to help us deal with the application service layer and the external data exchange.

ABP vNext in the application service module defines some common DTO objects, such as paging query entity DTO and DTO, DTO about these you just see it as a data container, do not need much attention, there is not much to Said.

Third, the summary

ABP vNext application service layer module is provided by a relatively simple, which is mainly the application service for a predefined base class. We developers to facilitate business development, without the need to implement these complex base class.

In DDD among application service is the expression of use cases and user stories primary means of application services just to express a demand by the assembly in accordance with the target areas / service areas. Do not leak into the application business logic services which , this design will eventually lead to anemia domain model.

Fourth, I click on to jump to an article directory

Guess you like

Origin www.cnblogs.com/myzony/p/11246623.html