Prerequisites: Strongbytes ASP.NET Core modular architecture
- The extension is created to work together with this modular architecture, that is the base for every Strongbytes new project;
- You should be familiar with how CQRS Pattern works together with Mediator Pattern to reduce dependencies between objects and separate read and update operations for a data store. We use MediatR in our modular architecture to accomplish this requirement;
- You should be familiar with Repository and Unit of Work Pattern. We implemented a Base Repository and a Base Unit of Work in the modular architecture, that can be easily extended;
- You should be familiar with IoC. We use Autofac IoC as the IoC Container;
- We use AutoMapper to simplify object mapping;
Open your solution and right-click any existing model (eg. LearningPath.cs
). Choose Generate Boilerplate Code...
from the menu:
Contains a TreeView of the selected entity hierarchy (including all containing models and the base class).
Target Module is used to specify which application module will contain all the generated files (except for Controller and DbContext);
Controller Location us used to specify which module is the main application module (the one where all Controllers are located);
You can specify if you want for the genrated CQRS files to use Unit of Work and Repository implementations (also generated by the extension). If this option is not selected, all CQRS classes will have the application DbContext as a dependency;
LearningPathDomainModel.cs
is the generated class that will be sent to the client as the result for all Controller Requests. It contains all the selected properties from Entity Hierarchy. The same properties are used to generated models specific for CQRS Commands (in this case only forCreateLearningPathRequestModel.cs
)
LearningPathsController.cs
is the generated API Controller, that contains all the selected Queries and Commands;
LearningPathsMapper.cs
contains all the generated object mappings. If the file does not exist, it will be created from scratch. If the file exists, the extension will find the existing mappings and will not replace them;
ILearningPathsRepository.cs
is the generated Repository Interface, that implementsIBaseRepository<LearningPath>
;
LearningPathsRepository.cs
is the implementation of theILearningPathsRepository
interface, that inherits fromBaseRepository<LearningPath>
IUnitOfWork.cs
is an interface that contains all the existing repositories (as interfaces). If the new generated repository (ILearningPathsRepository
) does not exist as a property, will be appended. This interface implementsIBaseUnitOfWork
LearningPathsModule.cs
is the Autofac module that registers all the services required for the Target Module. The extension will automatically registerILearningPathsRepository
,LearningPathsRepository
,IUnitOfWork
andUnitOfWork
(if not already registered);Commands
CreateLearningPathCommand.cs
,DeleteLearningPathCommand.cs
and QueriesGetLearningPathByIdQuery.cs
,GetPaginatedLearningPathsQuery.cs
implementIRequest<>
fromMediatR
. Every class of this type has a specific CQRS Handler;
- Create a new class that inherits
BaseGenericGeneratorModel
(eg.EntityRepositoryInterfaceGeneratorModel.cs
). Make sure that your class ends withGeneratorModel
, to match the naming guidelines for the other models; - Set the
Kind
property to a new enum value (eg.EntityRepositoryInterface
), that needs to be added toAssetKind
enum; - Go to
MetadataGenerationService
and add two new entries:AssetToCompilationUnitNameMapping (the name of the generated asset), exaple:
{ AssetKind.EntityRepositoryInterface, $"{CommonTokens.I}{BaseEntityPluralizedName}{CommonTokens.Repository}" }
AssetToNamespaceMapping (the containing namespace), example:
{ AssetKind.EntityRepositoryInterface, new NamespaceDefinitionModel { Content = $"{NamespaceTokens.Domain}.{NamespaceTokens.Repositories}", } }
- Override
UsingsBuilder
and include all the required usings; - Override
CompilationUnitDefinition
in order to:
public override CompilationUnitDefinitionModel CompilationUnitDefinition => new CompilationUnitDefinitionModel
{
Type = SyntaxKind.InterfaceDeclaration,
DefinedInheritanceTypes = new string[]
{
$"{CommonTokens.IBaseRepository}<{_viewModelBase.EntityTree.PrimaryEntityName()}>"
}
};