using System; using System.Linq; using Microsoft.AspNetCore.Builder; using Microsoft.EntityFrameworkCore; 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.Interfaces; using xDataService.Models; 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(); // 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 notProvided ..."); 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; } // // 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.Provider, descriptor.ConnectionString, lifetime, descriptor.OptionsBuilder ] ); // 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 => { // // Preparing Runtime Types ... Type[] runtimeTypes = r.GetType().GenericTypeArguments; // try { // typeof(XDataServiceHelper).InvokeGenericMethod( methodName: "AddXRepository", runtimeTypes: runtimeTypes, args: [ source, r, 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 ) { // // Validate ... var isValid = !source.IsNull() && descriptor.IsValid(); if (!isValid) { // Log("Invalid Database Configuration ..."); XException.InvalidArgs.Throw(); } // // Check Repositories Exists ... isValid = descriptor.HasRepositories(); if (isValid) { // // Create an Scope for Services Acces ... using (var scope = source.ApplicationServices.CreateScope()) { // // Inject XDataServiceConfiguration ForMake Sure DataService Registration ... var dataServiceConfiguration = scope.ServiceProvider.GetService(); isValid = !dataServiceConfiguration.IsNullOrDefault(); if (isValid) { // // Loop through Repositories ... descriptor.Repositories .ToList() .ForEach(r => { // // Check GraphQL Support ... isValid = r.HasGraphSupport(); if (isValid) { // // Inject GraphQL Type Helper ... var helper = scope.ServiceProvider.GetService(r.GraphTypeHelperService); isValid = !helper.IsNullOrDefault(); if (!isValid) { // Log($"unable to find GraphQLTypeHelper for Entiy: {r.Entity}"); XException.NotFound.Throw(); } // var methods = source.GetType().GetMethods(); isValid = !methods.IsNull() && methods.HasChild(); if (isValid) { // try { // // UseGraphQL ... var method = methods.First(m => m.IsGenericMethod && m.Name == "UseGraphQL" && m.GetGenericArguments().Length == 1 && m.GetParameters().Length == 1 ); var genericMethod = method.MakeGenericMethod(r.GraphSchema); genericMethod.Invoke(null, ((dynamic)helper).GetGraphQLPath()); // // UseGraphQLWebSockets ... method = methods.First(m => m.IsGenericMethod && m.Name == "UseGraphQLWebSockets" && m.GetGenericArguments().Length == 1 && m.GetParameters().Length == 0 ); genericMethod = method.MakeGenericMethod(r.GraphSchema); genericMethod.Invoke(null, null); // Log($"Register GraphQL Middleware for Entity {r.Entity} Successfully ..."); } catch (Exception ex) { Log($"Registration GraphQL Middleware for Entity {r.Entity} failed due {ex.Message} ..."); } } } }); } } } } // #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}"); } /// /// Do Seeding Initialization Data on DbContext /// /// private static void SeedData( this IApplicationBuilder app ) { // using (var scope = app.ApplicationServices.CreateScope()) { // var dbSeeder = scope.ServiceProvider.GetService(); Console.WriteLine($"XDataService: dbSeeder retrieved from DI is => {!dbSeeder.IsNull()}"); // if (!dbSeeder.IsNull()) { try { // dbSeeder.Seed() .GetAwaiter() .GetResult(); } catch (Exception ex) { // Console.WriteLine(" "); Console.WriteLine($"XDataService: Seeding Error: {ex.Message}"); XException.InvalidConfiguration.Throw(); } } } } #endregion } }