diff --git a/DI/XDIHelperExtension.cs b/DI/XDIHelperExtension.cs index a23b797..a4c2439 100644 --- a/DI/XDIHelperExtension.cs +++ b/DI/XDIHelperExtension.cs @@ -1,6 +1,5 @@ using System; using System.Linq; -using System.Reflection; using Microsoft.AspNetCore.Builder; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; @@ -10,7 +9,7 @@ using xCommons.Extensions; using xCommons.Helpers; using xDataService.Configuration; using xDataService.Constants; -using xDataService.Db; +using xDataService.Extensions; using xDataService.Helpers; using xDataService.Interfaces; using xDataService.Models; @@ -84,6 +83,13 @@ namespace xDataService.DI source.AddSingleton(configuration); } + /// + /// Register a Data Base using Descriptor ... + /// + /// + /// + /// + /// public static void AddXDatabase( this IServiceCollection source, IConfiguration configuration, @@ -162,35 +168,165 @@ namespace xDataService.DI !descriptor.ConnectionString.IsNullOrEmpty()) { // - typeof(XDataServiceHelper).InvokeGenericMethod( - methodName: "AddXDbContext", - runtimeType: descriptor.Context, - args: [ - source, + try + { + // + typeof(XDataServiceHelper).InvokeGenericMethod( + methodName: "AddXDbContext", + runtimeType: descriptor.Context, + args: [ + source, descriptor.Provider, descriptor.ConnectionString, lifetime, descriptor.OptionsBuilder - ] - ); + ] + ); - // - // source.AddXDbContext( - // lifetime: lifetime, - // provider: descriptor.Provider, - // optionsBuilder: descriptor.OptionsBuilder, - // connectionString: descriptor.ConnectionString - // ); + // + 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()) { - // source.AddXDataRepositories( + // + 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} ..."); + } + } + } + }); + } + } } } @@ -210,72 +346,6 @@ namespace xDataService.DI Console.WriteLine($"{XLogTag} => {message}"); } - /// - /// Register DbContext ... - /// - /// - /// - /// - /// - /// - /// - private static void AddXDbContext( - this IServiceCollection source, - XDbProviders provider, - string connectionString, - ServiceLifetime lifetime = ServiceLifetime.Scoped, - Action optionsBuilder = null - ) - where TContext : XDbContext - { - // - if (provider == XDbProviders.None) - { - // - Log("Invalid Db Provider ..."); - XException.InvalidArgs.Throw(); - } - - // - switch (provider) - { - // - // MySQL ... - case XDbProviders.MySQL: - // - source.AddDbContext(cfg => - { - cfg.UseMySQL(connectionString, optionsBuilder); - }, lifetime); - break; - - // - // SQLite ... - case XDbProviders.SQLite: - // - source.AddDbContext(cfg => - { - cfg.UseSqlite(connectionString, optionsBuilder); - }, lifetime); - break; - - // - // SQLServer ... - case XDbProviders.SQLServer: - // - source.AddDbContext(cfg => - { - cfg.UseSqlServer(connectionString, optionsBuilder); - }, lifetime); - break; - - // - case XDbProviders.MongoDB: - // There is notRequired to Register DBConext forMongo DB ... - break; - } - } - /// /// Do Seeding Initialization Data on DbContext /// diff --git a/Extensions/XDatabaseDescriptorExtensions.cs b/Extensions/XDatabaseDescriptorExtensions.cs new file mode 100644 index 0000000..779c027 --- /dev/null +++ b/Extensions/XDatabaseDescriptorExtensions.cs @@ -0,0 +1,57 @@ +using xCommons.Extensions; +using xDataService.Models; + +namespace xDataService.Extensions +{ + public static class XDatabaseDescriptorExtensions + { + /// + /// Validate a Database Descriptor ... + /// + /// + /// + public static bool IsValid(this XDatabaseDescriptor source) + { + // + var result = + !source.IsNull() && + !source.Name.IsNullOrEmpty(); + + // + return result; + } + + /// + /// Check a Descriptor Has EF Core Context or not ... + /// + /// + /// + public static bool HasContext(this XDatabaseDescriptor source) + { + // + var result = + source.IsValid() && + !source.Context.IsNull(); + + // + return result; + } + + /// + /// Check a Descriptor Has Repositories or not ... + /// + /// + /// + public static bool HasRepositories(this XDatabaseDescriptor source) + { + // + var result = + source.IsValid() && + !source.Repositories.IsNull() && + source.Repositories.HasChild(); + + // + return result; + } + } +} \ No newline at end of file diff --git a/Extensions/XRepositoryDescriptorExtensions.cs b/Extensions/XRepositoryDescriptorExtensions.cs new file mode 100644 index 0000000..aea5029 --- /dev/null +++ b/Extensions/XRepositoryDescriptorExtensions.cs @@ -0,0 +1,113 @@ +using xCommons.Extensions; +using xDataService.Models; + +namespace xDataService.Extensions +{ + public static class XRepositoryDescriptorExtensions + { + /// + /// Validate a Descriptor ... + /// + /// + /// + public static bool IsValid(this XRepositoryDescriptor source) + { + var result = + !source.IsNull() && + !source.Key.IsNull() && + !source.Entity.IsNull(); + + // + return result; + } + + /// + /// Check a Descriptor Has Events Service or not ... + /// + /// + /// + public static bool HasEvents(this XRepositoryDescriptor source) + { + // + var result = + source.IsValid() && + !source.EventsService.IsNull() && + !source.EventsImplementation.IsNull(); + + // + return result; + } + + /// + /// Check a Descriptor Has EF Core Context or not ... + /// + /// + /// + public static bool HasContext(this XRepositoryDescriptor source) + { + // + var result = + source.IsValid() && + !source.Context.IsNull(); + + // + return result; + } + + /// + /// Check a Descriptor Has GraphQL Support or not ... + /// + /// + /// + public static bool HasGraphSupport(this XRepositoryDescriptor source) + { + // + var result = + source.IsValid() && + !source.GraphType.IsNull() && + !source.GraphSchema.IsNull() && + !source.GraphTypeKey.IsNull() && + !source.GraphQueryService.IsNull() && + !source.GraphTypeHelperService.IsNull() && + !source.GraphQueryImplementation.IsNull() && + !source.GraphTypeHelperImplementation.IsNull(); + + // + return result; + } + + /// + /// Check a Descriptor Has Key Generator Service or not ... + /// + /// + /// + public static bool HasKeyGenerator(this XRepositoryDescriptor source) + { + // + var result = + source.IsValid() && + !source.KeyGeneratorService.IsNull() && + !source.KeyGeneratorImplementation.IsNull(); + + // + return result; + } + + /// + /// Check a Descriptor Has Repository Service or not ... + /// + /// + /// + public static bool HasRepository(this XRepositoryDescriptor source) + { + // + var result = + source.IsValid() && + !source.RepositoryService.IsNull() && + !source.RepositoryImplementation.IsNull(); + + // + return result; + } + } +} \ No newline at end of file diff --git a/Helpers/XDataServiceHelper.cs b/Helpers/XDataServiceHelper.cs index 8452268..f7338c2 100644 --- a/Helpers/XDataServiceHelper.cs +++ b/Helpers/XDataServiceHelper.cs @@ -1,10 +1,24 @@ using System; +using GraphQL.Server; +using GraphQL.Types; +using Microsoft.AspNetCore.Builder; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; +using MySql.EntityFrameworkCore.Extensions; using xCommons.Extensions; using xDataService.Constants; using xDataService.Db; +using xDataService.EFRepositories; +using xDataService.Events; +using xDataService.Extensions; +using xDataService.GraphQL; +using xDataService.InMemRepositories; +using xDataService.Interfaces; +using xDataService.Models; +using xDataService.MongoRepositories; +using xDataService.Providers; using xExceptions.Constants; +using xModels.Base; namespace xDataService.Helpers { @@ -43,6 +57,7 @@ namespace xDataService.Helpers // MySQL ... case XDbProviders.MySQL: // + source.AddEntityFrameworkMySQL(); source.AddDbContext(cfg => { cfg.UseMySQL(connectionString, optionsBuilder); @@ -53,6 +68,7 @@ namespace xDataService.Helpers // SQLite ... case XDbProviders.SQLite: // + source.AddEntityFrameworkSqlite(); source.AddDbContext(cfg => { cfg.UseSqlite(connectionString, optionsBuilder); @@ -63,6 +79,7 @@ namespace xDataService.Helpers // SQLServer ... case XDbProviders.SQLServer: // + source.AddEntityFrameworkSqlServer(); source.AddDbContext(cfg => { cfg.UseSqlServer(connectionString, optionsBuilder); @@ -74,6 +91,993 @@ namespace xDataService.Helpers // There is notRequired to Register DBConext forMongo DB ... break; } + + // + var isValid = + provider == XDbProviders.MySQL || + provider == XDbProviders.SQLite || + provider == XDbProviders.SQLServer; + if (isValid) + { + // + AddXUnitOfWorks( + source, + lifetime + ); + } } + + // + #region Repository ... + /// + /// Register Repository ... + /// + /// + /// + /// + /// + /// + /// + public static void AddXRepository( + IServiceCollection source, + XRepositoryDescriptor repositoryDescriptor, + ServiceLifetime lifetime = ServiceLifetime.Scoped + ) + where TEntity : XBaseEntity + { + // + var isValid = repositoryDescriptor.IsValid(); + if (!isValid) + { + return; + } + } + + /// + /// Register Repository ... + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static void AddXRepository( + IServiceCollection source, + XRepositoryDescriptor repositoryDescriptor, + ServiceLifetime lifetime = ServiceLifetime.Scoped + ) + where TEntity : XBaseEntity + where TKeyGeneratorService : IXKeyGenerator + where TKeyGeneratorImplementation : XKeyGenerator + { + // + var isValid = repositoryDescriptor.IsValid(); + if (!isValid) + { + return; + } + + // + // Register KeyGenerator ... + isValid = repositoryDescriptor.HasKeyGenerator(); + if (isValid) + { + // + AddXKeyGenerator( + source, + repositoryDescriptor, + lifetime + ); + } + } + + /// + /// Register Repository ... + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static void AddXRepository( + IServiceCollection source, + XRepositoryDescriptor repositoryDescriptor, + ServiceLifetime lifetime = ServiceLifetime.Scoped + ) + where TEntity : XBaseEntity + where TEventsService : IXBaseRepositoryEvents + where TKeyGeneratorService : IXKeyGenerator + where TEventsImplementation : XBaseRepositoryEvents + where TKeyGeneratorImplementation : XKeyGenerator + { + // + var isValid = repositoryDescriptor.IsValid(); + if (!isValid) + { + return; + } + + // + // Register KeyGenerator ... + isValid = repositoryDescriptor.HasKeyGenerator(); + if (isValid) + { + // + AddXKeyGenerator( + source, + repositoryDescriptor, + lifetime + ); + } + + // + // Register Events ... + isValid = repositoryDescriptor.HasEvents(); + if (isValid) + { + // + AddXEvents( + source, + repositoryDescriptor, + lifetime + ); + } + } + + /// + /// Register Repository ... + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static void AddXRepository( + IServiceCollection source, + XRepositoryDescriptor repositoryDescriptor, + ServiceLifetime lifetime = ServiceLifetime.Scoped + ) + where TGraphSchema : Schema + where TGraphKey : IGraphType + where TEntity : XBaseEntity + where TGraph : XBaseGraphObjectType + where TEventsService : IXBaseRepositoryEvents + where TKeyGeneratorService : IXKeyGenerator + where TEventsImplementation : XBaseRepositoryEvents + where TKeyGeneratorImplementation : XKeyGenerator + where TGraphTypeHelperService : IXBaseGraphQLTypeHelper + where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper + where TGraphQueryService : IXBaseGraphQLQuery + where TGraphQueryImplementation : XBaseGraphQLQuery + { + // + var isValid = repositoryDescriptor.IsValid(); + if (!isValid) + { + return; + } + + // + // Register KeyGenerator ... + isValid = repositoryDescriptor.HasKeyGenerator(); + if (isValid) + { + // + AddXKeyGenerator( + source, + repositoryDescriptor, + lifetime + ); + } + + // + // Register Events ... + isValid = repositoryDescriptor.HasEvents(); + if (isValid) + { + // + AddXEvents( + source, + repositoryDescriptor, + lifetime + ); + } + + // + // Register Graph ... + isValid = repositoryDescriptor.HasGraphSupport(); + if (isValid) + { + // + AddXGraphQL( + source, + repositoryDescriptor, + lifetime + ); + } + } + + /// + /// Register Repository ... + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static void AddXRepository( + IServiceCollection source, + XInMemoryRepositoryDescriptor repositoryDescriptor, + ServiceLifetime lifetime = ServiceLifetime.Scoped + ) + where TGraphSchema : Schema + where TGraphKey : IGraphType + where TEntity : XBaseEntity + where TGraph : XBaseGraphObjectType + where TEventsService : IXBaseRepositoryEvents + where TKeyGeneratorService : IXKeyGenerator + where TRepositoryService : IXBaseRepository + where TEventsImplementation : XBaseRepositoryEvents + where TKeyGeneratorImplementation : XKeyGenerator + where TGraphTypeHelperService : IXBaseGraphQLTypeHelper + where TRepositoryImplementation : XBaseInMemoryRepositoy + where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper + where TGraphQueryService : IXBaseGraphQLQuery + where TGraphQueryImplementation : XBaseGraphQLQuery + { + // + var isValid = repositoryDescriptor.IsValid(); + if (!isValid) + { + return; + } + + // + // Register KeyGenerator ... + isValid = repositoryDescriptor.HasKeyGenerator(); + if (isValid) + { + // + AddXKeyGenerator( + source, + repositoryDescriptor, + lifetime + ); + } + + // + // Register Events ... + isValid = repositoryDescriptor.HasEvents(); + if (isValid) + { + // + AddXEvents( + source, + repositoryDescriptor, + lifetime + ); + } + + // + // Register Graph ... + isValid = repositoryDescriptor.HasGraphSupport(); + if (isValid) + { + // + AddXGraphQL( + source, + repositoryDescriptor, + lifetime + ); + } + + // + // Register Repository ... + isValid = repositoryDescriptor.HasRepository(); + if (isValid) + { + // + source.Add( + new ServiceDescriptor( + repositoryDescriptor.RepositoryService, + repositoryDescriptor.RepositoryImplementation, + lifetime + ) + ); + } + } + + /// + /// Register Repository ... + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static void AddXRepository( + IServiceCollection source, + XMongoRepositoryDescriptor repositoryDescriptor, + ServiceLifetime lifetime = ServiceLifetime.Scoped + ) + where TGraphSchema : Schema + where TGraphKey : IGraphType + where TEntity : XBaseEntity + where TGraph : XBaseGraphObjectType + where TEventsService : IXBaseRepositoryEvents + where TKeyGeneratorService : IXKeyGenerator + where TRepositoryService : IXBaseRepository + where TEventsImplementation : XBaseRepositoryEvents + where TKeyGeneratorImplementation : XKeyGenerator + where TGraphTypeHelperService : IXBaseGraphQLTypeHelper + where TRepositoryImplementation : XBaseMongoRepository + where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper + where TGraphQueryService : IXBaseGraphQLQuery + where TGraphQueryImplementation : XBaseGraphQLQuery + { + // + var isValid = repositoryDescriptor.IsValid(); + if (!isValid) + { + return; + } + + // + // Register KeyGenerator ... + isValid = repositoryDescriptor.HasKeyGenerator(); + if (isValid) + { + // + AddXKeyGenerator( + source, + repositoryDescriptor, + lifetime + ); + } + + // + // Register Events ... + isValid = repositoryDescriptor.HasEvents(); + if (isValid) + { + // + AddXEvents( + source, + repositoryDescriptor, + lifetime + ); + } + + // + // Register Graph ... + isValid = repositoryDescriptor.HasGraphSupport(); + if (isValid) + { + // + AddXGraphQL( + source, + repositoryDescriptor, + lifetime + ); + } + + // + // Register Repository ... + isValid = repositoryDescriptor.HasRepository(); + if (isValid) + { + // + source.Add( + new ServiceDescriptor( + repositoryDescriptor.RepositoryService, + repositoryDescriptor.RepositoryImplementation, + lifetime + ) + ); + } + } + + /// + /// Register Repository ... + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static void AddXRepository( + IServiceCollection source, + XEFRepositoryDescriptor repositoryDescriptor, + ServiceLifetime lifetime = ServiceLifetime.Scoped + ) + where TGraphSchema : Schema + where TContext : XDbContext + where TGraphKey : IGraphType + where TEntity : XBaseEntity + where TGraph : XBaseGraphObjectType + where TEventsService : IXBaseRepositoryEvents + where TKeyGeneratorService : IXKeyGenerator + where TRepositoryService : IXBaseRepository + where TEventsImplementation : XBaseRepositoryEvents + where TKeyGeneratorImplementation : XKeyGenerator + where TGraphTypeHelperService : IXBaseGraphQLTypeHelper + where TRepositoryImplementation : XBaseEFRepository + where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper + where TGraphQueryService : IXBaseGraphQLQuery + where TGraphQueryImplementation : XBaseGraphQLQuery + { + // + var isValid = repositoryDescriptor.IsValid(); + if (!isValid) + { + return; + } + + // + // Register KeyGenerator ... + isValid = repositoryDescriptor.HasKeyGenerator(); + if (isValid) + { + // + AddXKeyGenerator( + source, + repositoryDescriptor, + lifetime + ); + } + + // + // Register Events ... + isValid = repositoryDescriptor.HasEvents(); + if (isValid) + { + // + AddXEvents( + source, + repositoryDescriptor, + lifetime + ); + } + + // + // Register Graph ... + isValid = repositoryDescriptor.HasGraphSupport(); + if (isValid) + { + // + AddXGraphQL( + source, + repositoryDescriptor, + lifetime + ); + } + + // + // Register Repository ... + isValid = repositoryDescriptor.HasRepository(); + if (isValid) + { + // + source.Add( + new ServiceDescriptor( + repositoryDescriptor.RepositoryService, + repositoryDescriptor.RepositoryImplementation, + lifetime + ) + ); + } + } + + /// + /// Register Repository ... + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static void UseXRepository( + IApplicationBuilder source, + XInMemoryRepositoryDescriptor repositoryDescriptor + ) + where TGraphSchema : Schema + where TGraphKey : IGraphType + where TEntity : XBaseEntity + where TGraph : XBaseGraphObjectType + where TEventsService : IXBaseRepositoryEvents + where TKeyGeneratorService : IXKeyGenerator + where TRepositoryService : IXBaseRepository + where TEventsImplementation : XBaseRepositoryEvents + where TKeyGeneratorImplementation : XKeyGenerator + where TGraphTypeHelperService : IXBaseGraphQLTypeHelper + where TRepositoryImplementation : XBaseInMemoryRepositoy + where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper + where TGraphQueryService : IXBaseGraphQLQuery + where TGraphQueryImplementation : XBaseGraphQLQuery + { + // + var isValid = repositoryDescriptor.IsValid(); + if (!isValid) + { + return; + } + + // + // GraphQL ... + isValid = repositoryDescriptor.HasGraphSupport(); + if (isValid) + { + // + UseXGraphQL( + source, + repositoryDescriptor + ); + } + } + + /// + /// Register Repository ... + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static void UseXRepository( + IApplicationBuilder source, + XMongoRepositoryDescriptor repositoryDescriptor + ) + where TGraphSchema : Schema + where TGraphKey : IGraphType + where TEntity : XBaseEntity + where TGraph : XBaseGraphObjectType + where TEventsService : IXBaseRepositoryEvents + where TKeyGeneratorService : IXKeyGenerator + where TRepositoryService : IXBaseRepository + where TEventsImplementation : XBaseRepositoryEvents + where TKeyGeneratorImplementation : XKeyGenerator + where TGraphTypeHelperService : IXBaseGraphQLTypeHelper + where TRepositoryImplementation : XBaseMongoRepository + where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper + where TGraphQueryService : IXBaseGraphQLQuery + where TGraphQueryImplementation : XBaseGraphQLQuery + { + // + var isValid = repositoryDescriptor.IsValid(); + if (!isValid) + { + return; + } + + // + // GraphQL ... + isValid = repositoryDescriptor.HasGraphSupport(); + if (isValid) + { + // + UseXGraphQL( + source, + repositoryDescriptor + ); + } + } + + /// + /// Register Repository ... + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static void UseXRepository( + IApplicationBuilder source, + XEFRepositoryDescriptor repositoryDescriptor + ) + where TGraphSchema : Schema + where TContext : XDbContext + where TGraphKey : IGraphType + where TEntity : XBaseEntity + where TGraph : XBaseGraphObjectType + where TEventsService : IXBaseRepositoryEvents + where TKeyGeneratorService : IXKeyGenerator + where TRepositoryService : IXBaseRepository + where TEventsImplementation : XBaseRepositoryEvents + where TKeyGeneratorImplementation : XKeyGenerator + where TGraphTypeHelperService : IXBaseGraphQLTypeHelper + where TRepositoryImplementation : XBaseEFRepository + where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper + where TGraphQueryService : IXBaseGraphQLQuery + where TGraphQueryImplementation : XBaseGraphQLQuery + { + // + var isValid = repositoryDescriptor.IsValid(); + if (!isValid) + { + return; + } + + // + // GraphQL ... + isValid = repositoryDescriptor.HasGraphSupport(); + if (isValid) + { + // + UseXGraphQL( + source, + repositoryDescriptor + ); + } + } + #endregion + + // + #region Private ... + /// + /// Register Unit of Works ... + /// + /// + /// + /// + public static void AddXUnitOfWorks( + IServiceCollection source, + ServiceLifetime lifetime = ServiceLifetime.Scoped + ) + where TContext : XDbContext + { + // + source.Add( + new ServiceDescriptor( + typeof(IXUnitOfWorks), + typeof(XUnitOfWorks), + lifetime + ) + ); + } + + /// + /// Register Key Generator Service ... + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static void AddXKeyGenerator( + IServiceCollection source, + XRepositoryDescriptor repositoryDescriptor, + ServiceLifetime lifetime = ServiceLifetime.Scoped + ) + where TEntity : XBaseEntity + where TKeyGeneratorService : IXKeyGenerator + where TKeyGeneratorImplementation : XKeyGenerator + { + // + // Validate ... + var isValid = + !source.IsNull() && + !repositoryDescriptor.IsNull() && + !repositoryDescriptor.KeyGeneratorService.IsNull() && + !repositoryDescriptor.KeyGeneratorImplementation.IsNull(); + if (!isValid) + { + return; + } + + // + // Register ... + source.Add( + new ServiceDescriptor( + repositoryDescriptor.KeyGeneratorService, + repositoryDescriptor.KeyGeneratorImplementation, + lifetime + ) + ); + } + + /// + /// Register Events Service ... + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static void AddXEvents( + IServiceCollection source, + XRepositoryDescriptor repositoryDescriptor, + ServiceLifetime lifetime = ServiceLifetime.Scoped + ) + where TEntity : XBaseEntity + where TEventsService : IXBaseRepositoryEvents + where TEventsImplementation : XBaseRepositoryEvents + { + // + // Validate ... + var isValid = + !source.IsNull() && + !repositoryDescriptor.IsNull() && + !repositoryDescriptor.EventsService.IsNull() && + !repositoryDescriptor.EventsImplementation.IsNull(); + if (!isValid) + { + return; + } + + // + // Register ... + source.Add( + new ServiceDescriptor( + repositoryDescriptor.EventsService, + repositoryDescriptor.EventsImplementation, + lifetime + ) + ); + } + + /// + /// Register GraphQL Service ... + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static void AddXGraphQL( + IServiceCollection source, + XRepositoryDescriptor repositoryDescriptor, + ServiceLifetime lifetime = ServiceLifetime.Scoped + ) + where TGraphSchema : Schema + where TGraphKey : IGraphType + where TEntity : XBaseEntity + where TGraph : XBaseGraphObjectType + where TGraphTypeHelperService : IXBaseGraphQLTypeHelper + where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper + where TGraphQueryService : IXBaseGraphQLQuery + where TGraphQueryImplementation : XBaseGraphQLQuery + { + // + // Validate ... + var isValid = + !source.IsNull() && + !repositoryDescriptor.IsNull() && + !repositoryDescriptor.GraphType.IsNull() && + !repositoryDescriptor.GraphSchema.IsNull() && + !repositoryDescriptor.GraphTypeKey.IsNull() && + !repositoryDescriptor.GraphQueryService.IsNull() && + !repositoryDescriptor.GraphTypeHelperService.IsNull() && + !repositoryDescriptor.GraphQueryImplementation.IsNull() && + !repositoryDescriptor.GraphTypeHelperImplementation.IsNull(); + if (!isValid) + { + return; + } + + // + // Register Graph Type ... + var builder = source.GetRegisteredService(); + if (builder.IsNull()) + { + // + Action options = x => { }; + builder = source.AddGraphQL(options) + .AddNewtonsoftJson(deserializerSettings => { }, serializerSettings => { }) + .AddWebSockets() + .AddDataLoader() + .AddGraphTypes(); + } + builder.AddGraphTypes(repositoryDescriptor.GraphType); + + // + // Register Graph Schema ... + source.Add( + new ServiceDescriptor( + repositoryDescriptor.GraphSchema, + repositoryDescriptor.GraphSchema, + lifetime + ) + ); + + // + // Register Graph Query ... + source.Add( + new ServiceDescriptor( + repositoryDescriptor.GraphQueryService, + repositoryDescriptor.GraphQueryImplementation, + lifetime + ) + ); + + // + // Register Graph Type Helper ... + source.Add( + new ServiceDescriptor( + repositoryDescriptor.GraphTypeHelperService, + repositoryDescriptor.GraphTypeHelperImplementation, + lifetime: ServiceLifetime.Singleton + ) + ); + } + + /// + /// Use GraphQL Middleware ... + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static void UseXGraphQL( + IApplicationBuilder source, + XRepositoryDescriptor repositoryDescriptor + ) + where TGraphSchema : Schema + where TGraphKey : IGraphType + where TEntity : XBaseEntity + where TGraph : XBaseGraphObjectType + where TGraphTypeHelperService : IXBaseGraphQLTypeHelper + where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper + where TGraphQueryService : IXBaseGraphQLQuery + where TGraphQueryImplementation : XBaseGraphQLQuery + { + // + // Validate ... + var isValid = + !source.IsNull() && + !repositoryDescriptor.IsNull() && + !repositoryDescriptor.GraphType.IsNull() && + !repositoryDescriptor.GraphSchema.IsNull() && + !repositoryDescriptor.GraphTypeKey.IsNull() && + !repositoryDescriptor.GraphQueryService.IsNull() && + !repositoryDescriptor.GraphTypeHelperService.IsNull() && + !repositoryDescriptor.GraphQueryImplementation.IsNull() && + !repositoryDescriptor.GraphTypeHelperImplementation.IsNull(); + if (!isValid) + { + return; + } + + // + // Create an Scope for Services Acces ... + using (var scope = source.ApplicationServices.CreateScope()) + { + // + // Inject GraphQL Type Helper ... + var helper = scope.ServiceProvider.GetService(); + + // + source.UseGraphQL(helper.GetGraphQLPath()); + source.UseGraphQLWebSockets(); + } + } + #endregion } } \ No newline at end of file diff --git a/Models/XRepositoryDescriptor.cs b/Models/XRepositoryDescriptor.cs index 7aba507..6fc01f7 100644 --- a/Models/XRepositoryDescriptor.cs +++ b/Models/XRepositoryDescriptor.cs @@ -1,6 +1,13 @@ +using System; using GraphQL.Types; +using xDataService.Db; +using xDataService.EFRepositories; +using xDataService.Events; using xDataService.GraphQL; +using xDataService.InMemRepositories; using xDataService.Interfaces; +using xDataService.MongoRepositories; +using xDataService.Providers; using xModels.Base; namespace xDataService.Models @@ -8,7 +15,104 @@ namespace xDataService.Models /// /// a Global non Generic Repository Descriptor ... /// - public class XRepositoryDescriptor { } + public class XRepositoryDescriptor + { + /// + /// Entity Key Type ... + /// + /// + public Type Key { get; set; } = null; + + /// + /// Entity Type ... + /// + /// + public Type Entity { get; set; } = null; + + /// + /// Context Type ... + /// + /// + public Type Context { get; set; } = null; + + /// + /// Graph Type Key ... + /// + /// + public Type GraphTypeKey { get; set; } = null; + + /// + /// Graph Type ... + /// + /// + public Type GraphType { get; set; } = null; + + /// + /// Entity Type GraphQL Schema ... + /// + /// + public Type GraphSchema { get; set; } = null; + + /// + /// Entity GraphQL Type Helper ... + /// + /// + public Type GraphTypeHelperService { get; set; } = null; + + /// + /// Entity GraphQL Type Helper ... + /// + /// + public Type GraphTypeHelperImplementation { get; set; } = null; + + /// + /// Entity GrapQL Query ... + /// + /// + public Type GraphQueryService { get; set; } = null; + + /// + /// Entity GrapQL Query ... + /// + /// + public Type GraphQueryImplementation { get; set; } = null; + + /// + /// Repository Event Provider ... + /// + /// + public Type EventsService { get; set; } = null; + + /// + /// Repository Event Provider ... + /// + /// + public Type EventsImplementation { get; set; } = null; + + /// + /// Repository Key Generator for Entity ... + /// + /// + public Type KeyGeneratorService { get; set; } = null; + + /// + /// Repository Key Generator for Entity ... + /// + /// + public Type KeyGeneratorImplementation { get; set; } = null; + + /// + /// Repository Data Access Design Pattern ... + /// + /// + public Type RepositoryService { get; set; } + + /// + /// Repository Data Access Design Pattern ... + /// + /// + public Type RepositoryImplementation { get; set; } + } /// /// a Repository Descriptor ... @@ -18,46 +122,158 @@ namespace xDataService.Models public class XRepositoryDescriptor : XRepositoryDescriptor where TEntity : XBaseEntity { - /// - /// Entity Type GraphQL Schema ... - /// - /// - public Schema GraphSchema { get; set; } = null; + public XRepositoryDescriptor() : base() + { + // + Key = typeof(TKey); + Entity = typeof(TEntity); + } + } - /// - /// Entity GraphQL Type Helper ... - /// - /// - public IXBaseGraphQLTypeHelper GraphTypeHelper { get; set; } = null; + /// + /// a Repository Descriptor ... + /// + public class XRepositoryDescriptor : XRepositoryDescriptor + where TEntity : XBaseEntity + where TKeyGeneratorService : IXKeyGenerator + where TKeyGeneratorImplementation : XKeyGenerator + { + public XRepositoryDescriptor() : base() + { + // + KeyGeneratorService = typeof(TKeyGeneratorService); + KeyGeneratorImplementation = typeof(TKeyGeneratorImplementation); + } + } - /// - /// Entity GrapQL Query ... - /// - /// - public IXBaseGraphQLQuery GraphQuery { get; set; } = null; + /// + /// a Repository Descriptor ... + /// + public class XRepositoryDescriptor : XRepositoryDescriptor + where TEntity : XBaseEntity + where TEventsService : IXBaseRepositoryEvents + where TKeyGeneratorService : IXKeyGenerator + where TEventsImplementation : XBaseRepositoryEvents + where TKeyGeneratorImplementation : XKeyGenerator + { + public XRepositoryDescriptor() : base() + { + // + EventsService = typeof(TEventsService); + EventsImplementation = typeof(TEventsImplementation); + } + } - /// - /// Entity GraphQL Type ... - /// - /// - public XBaseGraphObjectType GraphType { get; set; } = null; + /// + /// a Repository Descriptor ... + /// + public class XRepositoryDescriptor : XRepositoryDescriptor + where TGraphSchema : Schema + where TGraphKey : IGraphType + where TEntity : XBaseEntity + where TGraph : XBaseGraphObjectType + where TEventsService : IXBaseRepositoryEvents + where TKeyGeneratorService : IXKeyGenerator + where TEventsImplementation : XBaseRepositoryEvents + where TKeyGeneratorImplementation : XKeyGenerator + where TGraphTypeHelperService : IXBaseGraphQLTypeHelper + where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper + where TGraphQueryService : IXBaseGraphQLQuery + where TGraphQueryImplementation : XBaseGraphQLQuery + { + public XRepositoryDescriptor() : base() + { + // + GraphType = typeof(TGraph); + GraphTypeKey = typeof(TGraphKey); + GraphSchema = typeof(TGraphSchema); + GraphQueryService = typeof(TGraphQueryService); + GraphTypeHelperService = typeof(TGraphTypeHelperService); + GraphQueryImplementation = typeof(TGraphQueryImplementation); + GraphTypeHelperImplementation = typeof(TGraphTypeHelperImplementation); + } + } - /// - /// Repository Event Provider ... - /// - /// - public IXBaseRepositoryEvents Events { get; set; } = null; + /// + /// a Repository Descriptor ... + /// + public class XInMemoryRepositoryDescriptor : XRepositoryDescriptor + where TGraphSchema : Schema + where TGraphKey : IGraphType + where TEntity : XBaseEntity + where TGraph : XBaseGraphObjectType + where TEventsService : IXBaseRepositoryEvents + where TKeyGeneratorService : IXKeyGenerator + where TRepositoryService : IXBaseRepository + where TEventsImplementation : XBaseRepositoryEvents + where TKeyGeneratorImplementation : XKeyGenerator + where TGraphTypeHelperService : IXBaseGraphQLTypeHelper + where TRepositoryImplementation : XBaseInMemoryRepositoy + where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper + where TGraphQueryService : IXBaseGraphQLQuery + where TGraphQueryImplementation : XBaseGraphQLQuery + { + public XInMemoryRepositoryDescriptor() : base() + { + // + RepositoryService = typeof(TRepositoryService); + RepositoryImplementation = typeof(TRepositoryImplementation); + } + } - /// - /// Repository Key Generator for Entity ... - /// - /// - public IXKeyGenerator KeyGenerator { get; set; } = null; + /// + /// a Repository Descriptor ... + /// + public class XMongoRepositoryDescriptor : XRepositoryDescriptor + where TGraphSchema : Schema + where TGraphKey : IGraphType + where TEntity : XBaseEntity + where TGraph : XBaseGraphObjectType + where TEventsService : IXBaseRepositoryEvents + where TKeyGeneratorService : IXKeyGenerator + where TRepositoryService : IXBaseRepository + where TEventsImplementation : XBaseRepositoryEvents + where TKeyGeneratorImplementation : XKeyGenerator + where TRepositoryImplementation : XBaseMongoRepository + where TGraphTypeHelperService : IXBaseGraphQLTypeHelper + where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper + where TGraphQueryService : IXBaseGraphQLQuery + where TGraphQueryImplementation : XBaseGraphQLQuery + { + public XMongoRepositoryDescriptor() : base() + { + // + RepositoryService = typeof(TRepositoryService); + RepositoryImplementation = typeof(TRepositoryImplementation); + } + } - /// - /// Repository Data Access Design Pattern ... - /// - /// - public IXBaseRepository Repository { get; set; } + /// + /// a Repository Descriptor ... + /// + public class XEFRepositoryDescriptor : XRepositoryDescriptor + where TGraphSchema : Schema + where TContext : XDbContext + where TGraphKey : IGraphType + where TEntity : XBaseEntity + where TGraph : XBaseGraphObjectType + where TEventsService : IXBaseRepositoryEvents + where TKeyGeneratorService : IXKeyGenerator + where TRepositoryService : IXBaseRepository + where TEventsImplementation : XBaseRepositoryEvents + where TKeyGeneratorImplementation : XKeyGenerator + where TGraphTypeHelperService : IXBaseGraphQLTypeHelper + where TRepositoryImplementation : XBaseEFRepository + where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper + where TGraphQueryService : IXBaseGraphQLQuery + where TGraphQueryImplementation : XBaseGraphQLQuery + { + public XEFRepositoryDescriptor() : base() + { + // + Context = typeof(TContext); + RepositoryService = typeof(TRepositoryService); + RepositoryImplementation = typeof(TRepositoryImplementation); + } } } \ No newline at end of file diff --git a/Providers/XGuidKeyGenerator.cs b/Providers/XGuidKeyGenerator.cs index 16efd17..24b64f9 100644 --- a/Providers/XGuidKeyGenerator.cs +++ b/Providers/XGuidKeyGenerator.cs @@ -11,7 +11,7 @@ namespace xDataService.Providers /// Default Guid Key Generator ... /// /// - public class XGuidKeyGenerator : IXKeyGenerator + public class XGuidKeyGenerator : XKeyGenerator, IXKeyGenerator where TEntity : XBaseEntity { private readonly IXSequentialGuid sequentialGuid; @@ -23,7 +23,7 @@ namespace xDataService.Providers this.sequentialGuid = sequentialGuid; } - public async Task GenerateKey( + public override async Task GenerateKey( IXBaseRepository repository, CancellationToken cancellationToken = default ) @@ -44,7 +44,7 @@ namespace xDataService.Providers }, cancellationToken: cancellationToken); } - public bool IsEmpty(Guid id) + public override bool IsEmpty(Guid id) { // var result = id.IsNull() || id.IsDefaultGuid(); diff --git a/Providers/XIntKeyGenerator.cs b/Providers/XIntKeyGenerator.cs index a80e7f6..5355346 100644 --- a/Providers/XIntKeyGenerator.cs +++ b/Providers/XIntKeyGenerator.cs @@ -12,10 +12,10 @@ namespace xDataService.Providers /// Default Int Key Generator ... /// /// - public class XIntKeyGenerator : IXKeyGenerator + public class XIntKeyGenerator : XKeyGenerator, IXKeyGenerator where TEntity : XBaseEntity { - public async Task GenerateKey( + public override async Task GenerateKey( IXBaseRepository repository, CancellationToken cancellationToken = default ) @@ -33,7 +33,7 @@ namespace xDataService.Providers return result; } - public bool IsEmpty(int id) + public override bool IsEmpty(int id) { // var result = id <= 0; diff --git a/Providers/XKeyGenerator.cs b/Providers/XKeyGenerator.cs new file mode 100644 index 0000000..5b57fec --- /dev/null +++ b/Providers/XKeyGenerator.cs @@ -0,0 +1,18 @@ +using System.Threading; +using System.Threading.Tasks; +using xDataService.Interfaces; +using xModels.Base; + +namespace xDataService.Providers +{ + public abstract class XKeyGenerator : IXKeyGenerator + where TEntity : XBaseEntity + { + public abstract Task GenerateKey( + IXBaseRepository repository, + CancellationToken cancellationToken = default + ); + + public abstract bool IsEmpty(TKey id); + } +} \ No newline at end of file diff --git a/Providers/XStringKeyGenerator.cs b/Providers/XStringKeyGenerator.cs index 86c4c31..94fb246 100644 --- a/Providers/XStringKeyGenerator.cs +++ b/Providers/XStringKeyGenerator.cs @@ -12,7 +12,7 @@ namespace xDataService.Providers /// /// - public class XStringKeyGenerator : IXKeyGenerator + public class XStringKeyGenerator : XKeyGenerator, IXKeyGenerator where TEntity : XBaseEntity { private readonly IXSequentialGuid sequentialGuid; @@ -22,7 +22,7 @@ namespace xDataService.Providers this.sequentialGuid = sequentialGuid; } - public async Task GenerateKey( + public override async Task GenerateKey( IXBaseRepository repository, CancellationToken cancellationToken = default ) @@ -41,7 +41,7 @@ namespace xDataService.Providers } } - public bool IsEmpty(string id) + public override bool IsEmpty(string id) { return id.IsNullOrEmpty(); }