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 AbpDddApplicationModule
code.
[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
, IUnitOfWOrkEnabled
three interface types. With the addition of three types, ABP vNext according to the application service class to create a controller, this will be IgnoredInterfaces
what 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 ApplicationService
and a simple Crud base class CrudAppService
for our use, but the former inherited IApplicationService
interface, 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 ApplicationService
implement 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 IAvoidDuplicateCrossCuttingConcerns
interface, 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 List
writes 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 List
container 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
, ITransientDependency
interface 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 ICurrentUser
components, to get the current tenant of the ICurrentTenant
components, 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 AbpAuthorizationException
an 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 protected
modified, 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.