This commit is contained in:
2026-05-08 04:30:04 +03:30
parent afe5c74d09
commit 34afd95640
20 changed files with 1022 additions and 713 deletions
+208 -514
View File
@@ -1,590 +1,278 @@
using System;
using System.Collections.Generic;
using System.Linq;
using GraphQL.Server;
using GraphQL.Server.Ui.Playground;
using System.Reflection;
using Microsoft.AspNetCore.Builder;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Conventions;
using MySql.EntityFrameworkCore.Extensions;
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;
using xExceptions.Constants;
using xModels.Base;
namespace xDataService.DI {
public static class XDIHelperExtension {
/// <summary>
/// Extract Connection String From IConfiguration
/// </summary>
/// <param name="config"></param>
/// <param name="connectionName"></param>
/// <returns></returns>
public static string GetXConnectionString (
this IConfiguration config,
string connectionName = null
) {
//
if (connectionName.IsNullOrEmpty ()) {
connectionName = XDbProviderConfigurations.DEFAULT_CONNECTION_NAME;
}
//
return config.GetConnectionString (connectionName);
}
/// <summary>
/// Retrieve Data Provider Type from Configurations
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static XDbProviders GetXDbProviderType (this IConfiguration source) {
//
var provider = (source[$"{ConfigurationNodeNames.DB_PROVIDER_NODE}"])
.ToNormalString ();
//
return provider.ToDbProvider ();
}
namespace xDataService.DI
{
public static partial class XDIHelperExtension
{
/// <summary>
/// Retrive XDataService Configurations
/// </summary>
/// <param name="source"></param>
/// <param name="connectionName"></param>
/// <returns></returns>
public static XDataServiceConfiguration GetXDataServiceConfiguration (
this IConfiguration source,
string connectionName = null
) {
public static XDataServiceConfiguration GetXDataServiceConfiguration(
this IConfiguration source
)
{
//
var xDataServiceConfigSection = source
.GetSection (ConfigurationNodeNames.DATA_SERVICE_NODE);
var result = xDataServiceConfigSection.Get<XDataServiceConfiguration> ();
//
result.Provider = source.GetXDbProviderType ();
result.ConnectionString = source.GetXConnectionString (connectionName);
.GetSection(ConfigurationNodeNames.DATA_SERVICE_NODE);
var result = xDataServiceConfigSection.Get<XDataServiceConfiguration>();
//
return result;
}
/// <summary>
/// Register XDataService Configuration
/// Register XDataService Configuration ...
/// </summary>
/// <param name="services"></param>
/// <param name="source"></param>
/// <param name="configuration"></param>
/// <param name="connectionName"></param>
public static void AddXDataServiceConfiguration (
this IServiceCollection services,
IConfiguration configuration,
string connectionName = null
) {
public static void AddXDataServiceConfiguration(
this IServiceCollection source,
IConfiguration configuration
)
{
//
var dataServiceConfiguration = configuration
.GetXDataServiceConfiguration (connectionName);
if (dataServiceConfiguration.IsNull ()) {
dataServiceConfiguration = new XDataServiceConfiguration ();
var config = configuration.GetXDataServiceConfiguration();
if (config.IsNullOrDefault())
{
//
Log("Configurations Not Founded ...");
XException.NotFound.Throw();
}
//
services.AddSingleton<XDataServiceConfiguration> (dataServiceConfiguration);
source.AddSingleton(config);
}
/// <summary>
/// Register XDataService Configuration
/// Register XDataService Configuration ...
/// </summary>
/// <param name="services"></param>
/// <param name="source"></param>
/// <param name="configuration"></param>
public static void AddXDataServiceConfiguration (
this IServiceCollection services,
public static void AddXDataServiceConfiguration(
this IServiceCollection source,
XDataServiceConfiguration configuration
) {
)
{
//
if (configuration.IsNull ()) {
configuration = new XDataServiceConfiguration ();
if (configuration.IsNullOrDefault())
{
//
Log("Configurations Not Founded ...");
XException.NotFound.Throw();
}
//
services.AddSingleton<XDataServiceConfiguration> (configuration);
source.AddSingleton(configuration);
}
/// <summary>
/// Register XDataService on DI
/// Only Used when EFCore Provider configured to use ...
/// </summary>
/// <param name="services"></param>
/// <param name="config"></param>
/// <param name="lifetime"></param>
/// <param name="connectionName"></param>
/// <param name="optionsBuilder"></param>
public static void AddXDataService<TDbContext, TDbSeeder> (
this IServiceCollection services,
IConfiguration config,
ServiceLifetime lifetime,
string connectionName = null,
Action<dynamic> optionsBuilder = null
public static void AddXDatabase(
this IServiceCollection source,
IConfiguration configuration,
XDatabaseDescriptor descriptor,
ServiceLifetime lifetime = ServiceLifetime.Scoped
)
where TDbContext : XDbContext
where TDbSeeder : IXDbSeeder {
{
//
// Register DataService Configuration ...
if (services.GetRegisteredService<XDataServiceConfiguration> ().IsNull ()) {
Console.WriteLine ($"XDataService: there is no provided DataService Config, try to register default ...");
services.AddXDataServiceConfiguration (config, connectionName);
}
//
// prevent from going forward if there is no Provider configured ...
var providerType = config.GetXDbProviderType ();
Console.WriteLine ($"XDataService: registered db provider type is => {providerType} ...");
if (providerType == XDbProviders.None) {
// Validate Database Descriptor ...
var isValid =
!descriptor.IsNullOrDefault() &&
!descriptor.Name.IsNullOrEmpty();
if (!isValid)
{
//
Log("Invalid Database Descriptor ...");
return;
}
//
// Retrieve IXDataServiceHelper ...
var dataServiceHelper = services.GetRegisteredService<IXDataServiceHelper> ();
if (!dataServiceHelper.IsNull ()) {
// Check Service Collection Validation ...
isValid =
!source.IsNull() &&
!configuration.IsNull();
if (!isValid)
{
//
// Use Db Context Helper ...
Console.WriteLine ($"XDataService: use provided IXDbContextHelper ...");
Log("Invalid Service Provider or Configuration ...");
return;
}
//
// Get Registere Data Service Configuration ...
var xDataServiceConfiguration = source
.GetRegisteredService<XDataServiceConfiguration>();
isValid = !xDataServiceConfiguration.IsNullOrDefault();
if (!isValid)
{
//
// Retrieve Connection String ...
var addContext = true;
var connectionString = config.GetXConnectionString (connectionName);
switch (providerType) {
// Extract Configuration from Configuration ...
xDataServiceConfiguration = configuration.GetXDataServiceConfiguration();
isValid = !xDataServiceConfiguration.IsNullOrDefault();
if (!isValid)
{
//
case XDbProviders.MySQL:
addContext = true;
services.AddEntityFrameworkMySQL ();
break;
//
case XDbProviders.SQLite:
addContext = true;
services.AddEntityFrameworkSqlite ();
break;
//
case XDbProviders.SQLServer:
addContext = true;
services.AddEntityFrameworkSqlServer ();
break;
//
case XDbProviders.MongoDB:
addContext = false;
break;
Log("DataService Configuration notProvided ...");
return;
}
//
// Register DbContext in DI ...
if (addContext) {
dataServiceHelper.AddDbContext (
services,
connectionString,
providerType,
// 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())
{
//
typeof(XDataServiceHelper).InvokeGenericMethod(
methodName: "AddXDbContext",
runtimeType: descriptor.Context,
args: [
source,
descriptor.Provider,
descriptor.ConnectionString,
lifetime,
optionsBuilder
);
//
// Register Unit Of Works ...
services.Add (new ServiceDescriptor (typeof (IXUnitOfWorks<TDbContext>), typeof (XUnitOfWorks<TDbContext>), lifetime));
}
descriptor.OptionsBuilder
]
);
//
// Comment this in related to Task no. 27 ...
// Register IXSequentialGuid for handle XBaseGuidEntities ...
// services.AddSingleton<IXSequentialGuid, XSequentialGuid> ();
//
// Register All Repository Patterns ...
AddRepositories<TDbContext, TDbSeeder> (services, config, lifetime, providerType);
} else {
Console.WriteLine ($"XDataService: there is no provided IXDbContextHelper, data service registration failed ...");
// source.AddXDbContext<TContext>(
// lifetime: lifetime,
// provider: descriptor.Provider,
// optionsBuilder: descriptor.OptionsBuilder,
// connectionString: descriptor.ConnectionString
// );
}
}
/// <summary>
/// Register XDataService on DI
/// Only Used when non EFCore Provider configured to use ...
/// </summary>
/// <param name="services"></param>
/// <param name="config"></param>
/// <param name="lifetime"></param>
/// <param name="connectionName"></param>
public static void AddXDataService<TDbSeeder> (
this IServiceCollection services,
IConfiguration config,
ServiceLifetime lifetime,
string connectionName = null
)
where TDbSeeder : IXDbSeeder {
//
// Register DataService Configuration ...
if (services.GetRegisteredService<XDataServiceConfiguration> ().IsNull ()) {
Console.WriteLine ($"XDataService: there is no provided DataService Config, try to register default ...");
services.AddXDataServiceConfiguration (config, connectionName);
}
// Register Repositories ...
if (!descriptor.Repositories.IsNull() &&
descriptor.Repositories.HasChild())
{
// source.AddXDataRepositories(
//
// prevent from going forward if there is no Provider configured ...
var providerType = config.GetXDbProviderType ();
Console.WriteLine ($"XDataService: registered db provider type is => {providerType} ...");
if (providerType == XDbProviders.None) {
return;
}
//
// Retrieve IXDataServiceHelper ...
var dataServiceHelper = services.GetRegisteredService<IXDataServiceHelper> ();
if (!dataServiceHelper.IsNull ()) {
//
// Use Db Context Helper ...
Console.WriteLine ($"XDataService: use provided IXDataServiceHelper ...");
//
// Retrieve Connection String ...
var connectionString = config.GetXConnectionString (connectionName);
switch (providerType) {
//
case XDbProviders.MySQL:
case XDbProviders.SQLite:
case XDbProviders.SQLServer:
Console.WriteLine ($"XDataService: for EF Provider Types use AddXDataService<TDbContext, TDbSeeder> instead of AddXDataService<TDbSeeder> ...");
XException.InvalidConfiguration.Throw ();
break;
//
case XDbProviders.MongoDB:
//
#region XBaseEntity Mappers ...
//
// Map ID as BsonId here ...
BsonClassMap.RegisterClassMap<XBaseEntity<Guid>> (cm => {
//
cm.AutoMap ();
cm.MapIdMember (c => c.Id);
});
BsonClassMap.RegisterClassMap<XBaseEntity<int>> (cm => {
//
cm.AutoMap ();
cm.MapIdMember (c => c.Id);
});
BsonClassMap.RegisterClassMap<XBaseEntity<string>> (cm => {
//
cm.AutoMap ();
cm.MapIdMember (c => c.Id);
});
#endregion
//
var conventionPacks = dataServiceHelper.MongoConventionPacks ();
if (!conventionPacks.IsNull ()) {
ConventionRegistry.Register (
nameof (
dataServiceHelper.MongoConventionPacks
),
conventionPacks,
type => !type.FullName
.IsNullOrEmpty ()
);
}
//
dataServiceHelper.RegisterMongoExtras ();
break;
}
//
// Comment this in related to Task no. 27 ...
// Register IXSequentialGuid for handle XBaseGuidEntities ...
// services.AddSingleton<IXSequentialGuid, XSequentialGuid> ();
//
// Register All Repository Patterns ...
AddRepositories<TDbSeeder> (services, config, lifetime, providerType);
} else {
Console.WriteLine ($"XDataService: there is no provided IXDbContextHelper, data service registration failed ...");
}
}
/// <summary>
/// Register XGraphQL service ...
/// </summary>
/// <param name="services"></param>
/// <param name="options"></param>
public static void AddXGraphQL (
this IServiceCollection services,
Action<GraphQLOptions> options = null
) {
//
var xGraphQLHelper = services.GetRegisteredService<IXGraphQLHelper> ();
if (!xGraphQLHelper.IsNull ()) {
//
xGraphQLHelper.AddXGraphEnumTypes (services);
xGraphQLHelper.AddXGraphObjectTypes (services);
xGraphQLHelper.AddXGraphInputTypes (services);
xGraphQLHelper.AddXGraphQueries (services);
xGraphQLHelper.AddXGraphMutations (services);
xGraphQLHelper.AddXGraphSubscriptions (services);
xGraphQLHelper.AddXGraphSchemas (services);
//
// Add GraphQL Server ...
if (options.IsNull ()) {
//
options = x => { };
Console.WriteLine ($"XDataService: there is no provided GraphQLOption, use default ...");
}
//
var xGraphQlBuilder = services.AddGraphQL (options)
.AddNewtonsoftJson (deserializerSettings => { }, serializerSettings => { })
.AddWebSockets ()
.AddDataLoader ()
.AddGraphTypes ();
//
xGraphQLHelper.AddXGraphTypes (xGraphQlBuilder);
} else {
Console.WriteLine ($"XDataService: there is no provided IXGraphQLHelper, data service registration failed ...");
}
}
/// <summary>
/// Use XDataService MiddleWare
/// </summary>
/// <param name="app"></param>
public static void UseXDataService (
this IApplicationBuilder app
) {
app.SeedData ();
}
/// <summary>
/// Use XGraphQL Middleware ...
/// </summary>
/// <param name="app"></param>
/// <param name="options"></param>
/// <param name="withPlayground"></param>
public static void UseXGraphQL (
this IApplicationBuilder app,
GraphQLPlaygroundOptions options = null,
bool withPlayground = true
) {
//
// Use GraphQl WebSockets ...
app.UseWebSockets ();
//
// Registered Graph Types ...
using (var scope = app.ApplicationServices.CreateScope ()) {
//
var xGraphQLHelper = scope.ServiceProvider.GetService<IXGraphQLHelper> ();
if (!xGraphQLHelper.IsNull ()) {
xGraphQLHelper.UseXGraph (app);
} else {
Console.WriteLine ($"XDataService: there is no provided IXGraphQLHelper, data service GraphQL not using ...");
}
}
//
// Use GraphQL Playground UI ...
if (withPlayground) {
app.UseGraphQLPlayground (options);
// );
}
}
//
#region Private ...
/// <summary>
/// Register Repositories on DI as Services
/// a LogTag for xDataService ...
/// </summary>
/// <param name="services"></param>
/// <param name="config"></param>
/// <param name="lifetime"></param>
/// <param name="provider"></param>
private static void AddRepositories<TDbContext, TDbSeeder> (
IServiceCollection services,
IConfiguration config,
ServiceLifetime lifetime,
XDbProviders provider
)
where TDbContext : XDbContext
where TDbSeeder : IXDbSeeder {
//
// Add Repositories Based On Provider Here ...
switch (provider) {
case XDbProviders.MySQL:
case XDbProviders.SQLite:
case XDbProviders.SQLServer:
AddEFRepositories<TDbContext> (services, lifetime);
break;
case XDbProviders.MongoDB:
Console.WriteLine ($"XDataService: for Mongo Provider Types use AddXDataService<TDbSeeder> instead of AddXDataService<TDbContext, TDbSeeder> ...");
XException.InvalidConfiguration.Throw ();
break;
}
private static string XLogTag = "xDataService";
//
// Retrieve IXDataServiceHelper ...
var dataServiceHelper = services.GetRegisteredService<IXDataServiceHelper> ();
if (dataServiceHelper.IsNull ()) {
//
Console.WriteLine ($"XDataService: there is no provided IXDataServiceHelper, db seeder registration failed ...");
return;
}
//
// Add DbSeeder Configuration ...
dataServiceHelper.AddDbSeederConfiguration (services, config);
//
// Add Db Seeder ...
dataServiceHelper.AddDbSeeder<TDbSeeder> (services, config, lifetime);
/// <summary>
/// print a log in Console ...
/// </summary>
/// <param name="message"></param>
private static void Log(string message)
{
Console.WriteLine($"{XLogTag} => {message}");
}
/// <summary>
/// Register Repositories on DI as Services
/// Register DbContext ...
/// </summary>
/// <param name="services"></param>
/// <param name="config"></param>
/// <param name="lifetime"></param>
/// <param name="source"></param>
/// <param name="provider"></param>
private static void AddRepositories<TDbSeeder> (
IServiceCollection services,
IConfiguration config,
ServiceLifetime lifetime,
XDbProviders provider
/// <param name="connectionString"></param>
/// <param name="lifetime"></param>
/// <param name="optionsBuilder"></param>
/// <typeparam name="TContext"></typeparam>
private static void AddXDbContext<TContext>(
this IServiceCollection source,
XDbProviders provider,
string connectionString,
ServiceLifetime lifetime = ServiceLifetime.Scoped,
Action<dynamic> optionsBuilder = null
)
where TDbSeeder : IXDbSeeder {
where TContext : XDbContext
{
//
// Add Repositories Based On Provider Here ...
switch (provider) {
if (provider == XDbProviders.None)
{
//
case XDbProviders.MySQL:
case XDbProviders.SQLite:
case XDbProviders.SQLServer:
Console.WriteLine ($"XDataService: for EF Provider Types use AddXDataService<TDbContext, TDbSeeder> instead of AddXDataService<TDbSeeder> ...");
XException.InvalidConfiguration.Throw ();
break;
Log("Invalid Db Provider ...");
XException.InvalidArgs.Throw();
}
//
switch (provider)
{
//
// MySQL ...
case XDbProviders.MySQL:
//
case XDbProviders.MongoDB:
AddMongoRepositories (services, lifetime);
source.AddDbContext<TContext>(cfg =>
{
cfg.UseMySQL(connectionString, optionsBuilder);
}, lifetime);
break;
}
//
// Retrieve IXDataServiceHelper ...
var dataServiceHelper = services.GetRegisteredService<IXDataServiceHelper> ();
if (dataServiceHelper.IsNull ()) {
//
Console.WriteLine ($"XDataService: there is no provided IXDataServiceHelper, db seeder registration failed ...");
return;
}
//
// Add DbSeeder Configuration ...
dataServiceHelper.AddDbSeederConfiguration (services, config);
//
// Add Db Seeder ...
dataServiceHelper.AddDbSeeder<TDbSeeder> (services, config, lifetime);
}
/// <summary>
/// Add Entity Framework Repositories
/// </summary>
/// <param name="services"></param>
/// <param name="lifetime"></param>
private static void AddEFRepositories<TDbContext> (
this IServiceCollection services,
ServiceLifetime lifetime
)
where TDbContext : XDbContext {
//
var repoServices = new List<ServiceDescriptor> ();
//
var dataServiceConfig = services.GetRegisteredService<XDataServiceConfiguration> ();
if (!dataServiceConfig.IsNull ()) {
//
// Register Base Repositories if Required ...
}
//
// Adding Services to DI ...
if (repoServices.Count > 0) {
repoServices
.ToList ()
.ForEach (s => services.Add (s));
}
//
// Retrieve IXDataServiceHelper ...
var dataServiceHelper = services.GetRegisteredService<IXDataServiceHelper> ();
if (!dataServiceHelper.IsNull ()) {
//
// Register Repositories ...
dataServiceHelper.AddRepositories (services, lifetime);
//
// Register KeyGenerators ...
dataServiceHelper.AddKeyGenerators (services);
}
}
/// <summary>
/// Add MongoDb Repositories
/// </summary>
/// <param name="services"></param>
/// <param name="lifetime"></param>
private static void AddMongoRepositories (
this IServiceCollection services,
ServiceLifetime lifetime
) {
//
var repoServices = new List<ServiceDescriptor> ();
//
var dataServiceConfig = services.GetRegisteredService<XDataServiceConfiguration> ();
if (!dataServiceConfig.IsNull ()) {
//
// Register Base Repositories if Required ...
}
//
// Adding Services to DI ...
if (repoServices.Count > 0) {
repoServices
.ToList ()
.ForEach (s => services.Add (s));
}
//
// Retrieve IXDataServiceHelper ...
var dataServiceHelper = services.GetRegisteredService<IXDataServiceHelper> ();
if (!dataServiceHelper.IsNull ()) {
//
// Register Repositories ...
dataServiceHelper.AddRepositories (services, lifetime);
// SQLite ...
case XDbProviders.SQLite:
//
source.AddDbContext<TContext>(cfg =>
{
cfg.UseSqlite(connectionString, optionsBuilder);
}, lifetime);
break;
//
// Register KeyGenerators ...
dataServiceHelper.AddKeyGenerators (services);
// SQLServer ...
case XDbProviders.SQLServer:
//
source.AddDbContext<TContext>(cfg =>
{
cfg.UseSqlServer(connectionString, optionsBuilder);
}, lifetime);
break;
//
case XDbProviders.MongoDB:
// There is notRequired to Register DBConext forMongo DB ...
break;
}
}
@@ -592,27 +280,33 @@ namespace xDataService.DI {
/// Do Seeding Initialization Data on DbContext
/// </summary>
/// <param name="app"></param>
private static void SeedData (
private static void SeedData(
this IApplicationBuilder app
) {
)
{
//
using (var scope = app.ApplicationServices.CreateScope ()) {
using (var scope = app.ApplicationServices.CreateScope())
{
//
var dbSeeder = scope.ServiceProvider.GetService<IXDbSeeder> ();
Console.WriteLine ($"XDataService: dbSeeder retrieved from DI is => {!dbSeeder.IsNull()}");
var dbSeeder = scope.ServiceProvider.GetService<IXDbSeeder>();
Console.WriteLine($"XDataService: dbSeeder retrieved from DI is => {!dbSeeder.IsNull()}");
//
if (!dbSeeder.IsNull ()) {
try {
if (!dbSeeder.IsNull())
{
try
{
//
dbSeeder.Seed ()
.GetAwaiter ()
.GetResult ();
} catch (Exception ex) {
dbSeeder.Seed()
.GetAwaiter()
.GetResult();
}
catch (Exception ex)
{
//
Console.WriteLine (" ");
Console.WriteLine ($"XDataService: Seeding Error: {ex.Message}");
XException.InvalidConfiguration.Throw ();
Console.WriteLine(" ");
Console.WriteLine($"XDataService: Seeding Error: {ex.Message}");
XException.InvalidConfiguration.Throw();
}
}
}