· 6 years ago · Oct 03, 2019, 03:20 AM
1using Microsoft.AspNetCore.Mvc;
2using Microsoft.EntityFrameworkCore;
3using Microsoft.Extensions.DependencyInjection;
4using System;
5using System.Collections.Generic;
6using System.Linq;
7using System.Text;
8using System.Threading.Tasks;
9
10namespace KosterLib
11{
12 /// <summary>
13 /// Api Controller Base, representing an Entity and related EFC Actions
14 /// </summary>
15 /// <typeparam name="Entity">Entity to Model using this controller class</typeparam>
16 /// <typeparam name="DataContextType">DataContext Type for DependencyInjection</typeparam>
17 [ApiController]
18 [Route("api/[controller]")]
19 public class ApiBase<Entity, DataContextType> : ControllerBase where Entity : class where DataContextType : DbContext
20 {
21 /// <summary>
22 /// The EFC DataContext Reference
23 /// </summary>
24 public DataContextType DataContext { get; set; }
25
26 /// <summary>
27 /// The DbSet containing the entities from the DB
28 /// </summary>
29 private DbSet<Entity> Entities { get; set; }
30
31 /// <summary>
32 /// Default constructor getting IServiceProvider for dependency injection
33 /// </summary>
34 /// <param name="serviceProvider">IServiceProvider for dependency injection</param>
35 public ApiBase(IServiceProvider serviceProvider)
36 {
37 DataContext = serviceProvider.GetService<DataContextType>();
38 Entities = DataContext.Set<Entity>();
39 }
40
41 #region Create Generic(s)
42 /// <summary>
43 /// Create an entity in the DataBase from a Dto Type, Make sure you call SaveChanges after this!
44 /// </summary>
45 /// <typeparam name="EntityPostDto">EntityPostDto Type for reference</typeparam>
46 /// <param name="dto">Dto Object to map into an Entity for adding</param>
47 /// <returns>Entity added to database</returns>
48 public async Task<Entity> CreateEntity<EntityPostDto>(EntityPostDto dto) where EntityPostDto : class =>
49 (await Entities.AddAsync(Map<EntityPostDto, Entity>(dto))).Entity;
50 #endregion
51
52 #region Read Generic(s)
53 /// <summary>
54 /// Get all Entities from the database and map to their respective Dto
55 /// </summary>
56 /// <typeparam name="EntityGetDto">The Dto Type to be mapped to</typeparam>
57 /// <returns>Array of Dto types of entities in the DB</returns>
58 public async Task<ICollection<EntityGetDto>> GetEntities<EntityGetDto>() where EntityGetDto : class =>
59 await Entities.Select(e => Map<Entity, EntityGetDto>(e)).ToArrayAsync();
60
61 /// <summary>
62 /// Get Entity from DB based on the key "Id"
63 /// </summary>
64 /// <typeparam name="KeyType">The type of the key</typeparam>
65 /// <param name="key">The value of the key to find</param>
66 /// <returns>The Entity result from the search by key</returns>
67 public async Task<Entity> GetEntityByKey<KeyType>(KeyType key) =>
68 await Entities.FindAsync(key);
69 #endregion
70
71 /// <summary>
72 /// Map from one type to another using an intersection of their properties
73 /// </summary>
74 /// <typeparam name="Source">The source type to map from</typeparam>
75 /// <typeparam name="Destination">The destination type to map to</typeparam>
76 /// <param name="source">The source object to be mapped from</param>
77 /// <returns>The mapped destination type of the object</returns>
78 private Destination Map<Source, Destination>(Source source) where Source : class where Destination : class
79 {
80 var sourceType = typeof(Source);
81 var destinationType = typeof(Destination);
82
83 var converted = (Destination)destinationType.GetConstructor(null).Invoke(null);
84
85 foreach (var propertyInfo in sourceType.GetProperties().Intersect(destinationType.GetProperties()))
86 destinationType.GetProperty(propertyInfo.Name).SetValue(converted, sourceType.GetProperty(propertyInfo.Name).GetValue(source));
87
88 return converted;
89 }
90 }
91}