using System; using System.Collections.Generic; using System.Linq; using Microsoft.AspNetCore.Builder; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using xCommons.Extensions; using xCommons.Helpers; using xDataService.Configuration; using xDataService.Constants; using xDataService.Extensions; using xDataService.Helpers; using xDataService.Models; using xDataService.Providers; using xExceptions.Constants; namespace xDataService.DI { public static partial class XDIHelperExtension { /// /// Retrive XDataService Configurations /// /// /// public static XDataServiceConfiguration GetXDataServiceConfiguration( this IConfiguration source ) { // var xDataServiceConfigSection = source .GetSection(ConfigurationNodeNames.DATA_SERVICE_NODE); var result = xDataServiceConfigSection.Get(); // // Reading Seeders ... if (!result.IsNull() && result.Databases.HasChild()) { // result .Databases .ToList() .ForEach(db => { // var seedItemsSectionName = $"{ConfigurationNodeNames.DATA_SERVICE_NODE}:{nameof(XDataServiceConfiguration.Databases)}:{db.Key}:{nameof(XDataBaseConfiguration.SeedItems)}"; var section = source.GetSection(seedItemsSectionName); var sectionJson = source.GetSectionAsJson(seedItemsSectionName); var sectionDict = sectionJson.FromJSON>>(); if (!sectionDict.IsNull() && sectionDict.Values.HasChild()) { // sectionDict .Keys .ToList() .ForEach(entity => { // // Setting Values to Result ... result.Databases[db.Key].SeedItems[entity] = sectionDict[entity]; }); } }); } // return result; } /// /// Register XDataService Configuration ... /// /// /// public static void AddXDataServiceConfiguration( this IServiceCollection source, IConfiguration configuration ) { // var config = configuration.GetXDataServiceConfiguration(); if (config.IsNullOrDefault()) { // Log("Configurations Not Founded ..."); XException.NotFound.Throw(); } // source.AddSingleton(config); } /// /// Register XDataService Configuration ... /// /// /// public static void AddXDataServiceConfiguration( this IServiceCollection source, XDataServiceConfiguration configuration ) { // if (configuration.IsNullOrDefault()) { // Log("Configurations Not Founded ..."); XException.NotFound.Throw(); } // source.AddSingleton(configuration); } /// /// Register a Data Base using Descriptor ... /// /// /// /// /// public static void AddXDatabase( this IServiceCollection source, IConfiguration configuration, XDatabaseDescriptor descriptor, ServiceLifetime lifeTime = ServiceLifetime.Scoped ) { // // Validate Database Descriptor ... var isValid = !descriptor.IsNullOrDefault() && !descriptor.Name.IsNullOrEmpty(); if (!isValid) { // Log("Invalid Database Descriptor ..."); return; } // // Check Service Collection Validation ... isValid = !source.IsNull() && !configuration.IsNull(); if (!isValid) { // Log("Invalid Service Provider or Configuration ..."); return; } // // Get Registere Data Service Configuration ... var xDataServiceConfiguration = source .GetRegisteredService(); isValid = !xDataServiceConfiguration.IsNullOrDefault(); if (!isValid) { // // Extract Configuration from Configuration ... xDataServiceConfiguration = configuration.GetXDataServiceConfiguration(); isValid = !xDataServiceConfiguration.IsNullOrDefault(); if (!isValid) { // Log("DataService Configuration not provided ..."); return; } // // Register Configuration in DI ... source.AddSingleton(xDataServiceConfiguration); } // // Check Data Service Configuration has Database ... isValid = !xDataServiceConfiguration.Databases.IsNullOrDefault() && xDataServiceConfiguration.Databases.HasChild() && xDataServiceConfiguration.Databases.Keys.Contains(descriptor.Name); if (!isValid) { // Log("Invalid Database Descriptor ..."); return; } // // Register Handler Service ... source.AddSingleton(); // // Configure Database Descriptor ... descriptor.Configure(source); // // Register Context ... if (!descriptor.Context.IsNull() && descriptor.Provider != XDbProviders.None && !descriptor.ConnectionString.IsNullOrEmpty()) { // try { // typeof(XDataServiceHelper).InvokeGenericMethod( methodName: "AddXDbContext", runtimeType: descriptor.Context, args: [ source, descriptor, lifeTime ] ); // Log($"DbContext: {descriptor.Name} Registered Successfully ..."); } catch (Exception ex) { Log($"DbContext: {descriptor.Name} Registration failed due {ex.Message} ..."); } } // // Register Repositories ... if (!descriptor.Repositories.IsNull() && descriptor.Repositories.HasChild()) { // descriptor.Repositories.ToList().ForEach(r => { // source.AddXRepository( descriptor: r, lifeTime: lifeTime ); }); } } public static void AddXRepository( this IServiceCollection source, XRepositoryDescriptor descriptor, ServiceLifetime lifeTime = ServiceLifetime.Scoped ) { // // Preparing Runtime Types ... Type[] runtimeTypes = descriptor.GetType().GenericTypeArguments; // try { // typeof(XDataServiceHelper).InvokeGenericMethod( methodName: "AddXRepository", runtimeTypes: runtimeTypes, args: [ source, descriptor, lifeTime ] ); // Log($"Repository of: {runtimeTypes[0]}, Registered Successfully ..."); } catch (Exception ex) { Log($"Repository of: {runtimeTypes[0]}, Registration failed due {ex.Message} ..."); } } public static void UseXDatabase( this IApplicationBuilder source, XDatabaseDescriptor descriptor, bool isDevelopmentEnvironment = false ) { // // Validate ... var isValid = !source.IsNull() && descriptor.IsValid(); if (!isValid) { // Log("Invalid Database Configuration ..."); XException.InvalidArgs.Throw(); } // // Check Repositories Exists ... isValid = descriptor.HasRepositories(); if (isValid) { // // Loop through Repositories ... descriptor.Repositories .ToList() .ForEach(r => { // source.UseXRepository( descriptor: r, isDevelopmentEnvironment: isDevelopmentEnvironment ); }); } } /// /// Use a Repository Middlewares by Providing it's Descriptor ... /// /// /// /// public static void UseXRepository( this IApplicationBuilder source, XRepositoryDescriptor descriptor, bool isDevelopmentEnvironment = false ) { // Log($"Start Using Repository of: {descriptor.Entity}"); // var withPlayground = false; if (isDevelopmentEnvironment) { withPlayground = true; } // // Create an Scope for Services Acces ... using (var scope = source.ApplicationServices.CreateScope()) { // // Inject XDataServiceConfiguration ForMake Sure DataService Registration ... var dataServiceConfiguration = scope.ServiceProvider.GetService(); var isValid = !dataServiceConfiguration.IsNullOrDefault(); if (isValid) { // // Check Seeder Exists ... // Execute Seeding Data Task if Exists ... isValid = descriptor.HasSeeder(); if (isValid) { // var seeder = (dynamic)scope.ServiceProvider.GetService(descriptor.SeederService); isValid = seeder != null; if (isValid) { // Log($"Start Seeding {descriptor.Entity} ..."); // // Seeding ... seeder .Seed() .GetAwaiter() .GetResult(); } } // // Check GraphQL Support ... isValid = descriptor.HasGraphSupport(); if (isValid) { // // Use WebSockets ... source.UseWebSockets(); // // Inject GraphQL Type Helper ... var helper = (dynamic)scope.ServiceProvider.GetService(descriptor.GraphTypeHelperService); isValid = helper != null; if (isValid) { // var graphPath = $"{helper.GetGraphQLPath()}"; var graphBasePath = $"{dataServiceConfiguration.GraphQLBasePath}"; typeof(XDataServiceHelper).InvokeGenericMethod( methodName: "UseXGraphQL", runtimeTypes: [ descriptor.Entity, descriptor.Key, descriptor.GraphType, descriptor.GraphTypeKey, descriptor.GraphQuery, descriptor.GraphTypeHelperService, descriptor.GraphTypeHelperImplementation, descriptor.GraphSchema ], args: [ source, graphBasePath, graphPath, withPlayground ] ); // Log($"Register GraphQL: {graphPath}"); } } } } } // #region Private ... /// /// a LogTag for xDataService ... /// private static string XLogTag = "xDataService"; /// /// print a log in Console ... /// /// private static void Log(string message) { Console.WriteLine($"{XLogTag} => {message}"); } #endregion } }