FirelyTeam / firely-cql-sdk

BSD 3-Clause "New" or "Revised" License
31 stars 17 forks source link

406 standarize on dependency injection strategy #501

Closed baseTwo closed 2 months ago

baseTwo commented 3 months ago

Work for #406

Refactored the factory types into helpers to add services to IServiceCollection

Removed the old factory types :

New types to simplify service construction

The following projects (see diagram below) contains services that can be added to a service collection, typically as part of a hosting environment. These projects all have a new sub-namespace called Hosting.

classDiagram
    direction BT
    Cql_Compiler ..> Cql_Runtime
    Cql_CqlToElm ..> Cql_Runtime
    CodeGeneration_NET ..> Cql_Compiler
    Cql_Packager ..> CodeGeneration_NET

Diagram of project hierarchy containing CQL services

The Cql.Runtime project doesn't have any services of its own that is used for the elm to c# pipeline, so its Hosting namespace only contains utility extensions needed by the other projects, such as ServiceCollectionExtensions and ServiceProviderExtensions.

For the other projects, their Hosting namespace have two types each, one to construct services into a IServiceCollection, and another to access services from IServiceProvider (which is primarily only used for unit testing). A consistent naming convention is used for types between all these projects: Cql*ServicesInitializer and Cql*Services.

Cql*ServicesInitialzer contains methods such as AddCql*Services and GetCql*Services.

Runtime Usage

To add services to IServiceCollection at runtime, just call any of the following

Test Usage

The CqlServicesInitializer is a helper to create services for the compiler or packager services.

// Create a context to which services will be registered to for disposal
using DisposeContext disposeContext = new DisposeContext();

// Get all the services for CQL code generation
CqlCodeGenerationServices cqlCodeGenerationServices = CqlServicesInitializer.CreateCqlCodeGenerationServices(disposeContext.Token);

// Get the CSharpLibrarySetToStreamsWriter 
CSharpLibrarySetToStreamsWriter writer = cqlCodeGenerationServices.CSharpLibrarySetToStreamsWriter;

// Direct access to services from dependency libraries possible with GetCqlCompilerServices()
LibraryExpressionBuilder libraryExpressionBuilder = cqlCodeGenerationServices.GetCqlCompilerServices().LibraryExpressionBuilder;

Cql-to-Elm

The same dependency injection pattern is used for cql to elm.

baseTwo commented 3 months ago

Discussed with @ewoutkramer that we add the same pattern to initialize and group services for the cql to elm project the same way