@@ -44,6 +44,18 @@ public abstract class AbstractKeyReadOnlyAppService<TEntity, TGetOutputDto, TGet
4444
4545 protected virtual string ? GetListPolicyName { get ; set ; }
4646
47+ protected virtual IQueryProjectionMapper < TEntity , TGetOutputDto > ? ObjectProjectionMapper =>
48+ LazyServiceProvider . LazyGetService < IQueryProjectionMapper < TEntity , TGetOutputDto > > ( ) ;
49+
50+ protected virtual IQueryProjectionMapper < TEntity , TGetListOutputDto > ? ListProjectionMapper =>
51+ LazyServiceProvider . LazyGetService < IQueryProjectionMapper < TEntity , TGetListOutputDto > > ( ) ;
52+
53+ protected virtual bool UseObjectProjectionMapper =>
54+ ObjectProjectionMapper != null ;
55+
56+ protected virtual bool UseListProjectionMapper =>
57+ ListProjectionMapper != null ;
58+
4759 protected AbstractKeyReadOnlyAppService ( IReadOnlyRepository < TEntity > repository )
4860 {
4961 ReadOnlyRepository = repository ;
@@ -53,6 +65,19 @@ public virtual async Task<TGetOutputDto> GetAsync(TKey id)
5365 {
5466 await CheckGetPolicyAsync ( ) ;
5567
68+ var projectionMapper = ObjectProjectionMapper ;
69+
70+ if ( UseObjectProjectionMapper && projectionMapper != null )
71+ {
72+ var query = await GetEntityByIdQueryAsync ( id ) ;
73+
74+ var dto =
75+ await AsyncExecuter . FirstOrDefaultAsync ( projectionMapper . ProjectTo ( query ) )
76+ ?? throw new EntityNotFoundException ( typeof ( TEntity ) , id ) ;
77+
78+ return dto ;
79+ }
80+
5681 var entity = await GetEntityByIdAsync ( id ) ;
5782
5883 return await MapToGetOutputDtoAsync ( entity ) ;
@@ -65,16 +90,26 @@ public virtual async Task<PagedResultDto<TGetListOutputDto>> GetListAsync(TGetLi
6590 var query = await CreateFilteredQueryAsync ( input ) ;
6691 var totalCount = await AsyncExecuter . CountAsync ( query ) ;
6792
68- var entities = new List < TEntity > ( ) ;
6993 var entityDtos = new List < TGetListOutputDto > ( ) ;
7094
7195 if ( totalCount > 0 )
7296 {
7397 query = ApplySorting ( query , input ) ;
7498 query = ApplyPaging ( query , input ) ;
7599
76- entities = await AsyncExecuter . ToListAsync ( query ) ;
77- entityDtos = await MapToGetListOutputDtosAsync ( entities ) ;
100+ var projectionMapper = ListProjectionMapper ;
101+
102+ if ( UseListProjectionMapper && projectionMapper != null )
103+ {
104+ entityDtos = await AsyncExecuter . ToListAsync (
105+ projectionMapper . ProjectTo ( query )
106+ ) ;
107+ }
108+ else
109+ {
110+ var entities = await AsyncExecuter . ToListAsync ( query ) ;
111+ entityDtos = await MapToGetListOutputDtosAsync ( entities ) ;
112+ }
78113 }
79114
80115 return new PagedResultDto < TGetListOutputDto > (
@@ -85,6 +120,13 @@ public virtual async Task<PagedResultDto<TGetListOutputDto>> GetListAsync(TGetLi
85120
86121 protected abstract Task < TEntity > GetEntityByIdAsync ( TKey id ) ;
87122
123+ protected virtual Task < IQueryable < TEntity > > GetEntityByIdQueryAsync ( TKey id )
124+ {
125+ throw new NotImplementedException (
126+ "Override this method to create the query used for getting an entity by id."
127+ ) ;
128+ }
129+
88130 protected virtual async Task CheckGetPolicyAsync ( )
89131 {
90132 await CheckPolicyAsync ( GetPolicyName ) ;
@@ -227,4 +269,4 @@ protected virtual TGetListOutputDto MapToGetListOutputDto(TEntity entity)
227269 {
228270 return ObjectMapper . Map < TEntity , TGetListOutputDto > ( entity ) ;
229271 }
230- }
272+ }
0 commit comments