622 lines
23 KiB
C#
622 lines
23 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using GraphQL.Server;
|
|
using GraphQL.Server.Ui.Playground;
|
|
using Microsoft.AspNetCore.Builder;
|
|
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 xDataService.Configuration;
|
|
using xDataService.Constants;
|
|
using xDataService.Db;
|
|
using xDataService.Extensions;
|
|
using xDataService.Interfaces;
|
|
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 ();
|
|
}
|
|
|
|
/// <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
|
|
) {
|
|
//
|
|
var xDataServiceConfigSection = source
|
|
.GetSection (ConfigurationNodeNames.DATA_SERVICE_NODE);
|
|
var result = xDataServiceConfigSection.Get<XDataServiceConfiguration> ();
|
|
|
|
//
|
|
result.Provider = source.GetXDbProviderType ();
|
|
result.ConnectionString = source.GetXConnectionString (connectionName);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Register XDataService Configuration
|
|
/// </summary>
|
|
/// <param name="services"></param>
|
|
/// <param name="configuration"></param>
|
|
/// <param name="connectionName"></param>
|
|
public static void AddXDataServiceConfiguration (
|
|
this IServiceCollection services,
|
|
IConfiguration configuration,
|
|
string connectionName = null
|
|
) {
|
|
//
|
|
var dataServiceConfiguration = configuration
|
|
.GetXDataServiceConfiguration (connectionName);
|
|
if (dataServiceConfiguration.IsNull ()) {
|
|
dataServiceConfiguration = new XDataServiceConfiguration ();
|
|
}
|
|
|
|
//
|
|
services.AddSingleton<XDataServiceConfiguration> (dataServiceConfiguration);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Register XDataService Configuration
|
|
/// </summary>
|
|
/// <param name="services"></param>
|
|
/// <param name="configuration"></param>
|
|
public static void AddXDataServiceConfiguration (
|
|
this IServiceCollection services,
|
|
XDataServiceConfiguration configuration
|
|
) {
|
|
//
|
|
if (configuration.IsNull ()) {
|
|
configuration = new XDataServiceConfiguration ();
|
|
}
|
|
|
|
//
|
|
services.AddSingleton<XDataServiceConfiguration> (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
|
|
)
|
|
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) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Retrieve IXDataServiceHelper ...
|
|
var dataServiceHelper = services.GetRegisteredService<IXDataServiceHelper> ();
|
|
if (!dataServiceHelper.IsNull ()) {
|
|
//
|
|
// Use Db Context Helper ...
|
|
Console.WriteLine ($"XDataService: use provided IXDbContextHelper ...");
|
|
|
|
//
|
|
// Retrieve Connection String ...
|
|
var addContext = true;
|
|
var connectionString = config.GetXConnectionString (connectionName);
|
|
switch (providerType) {
|
|
//
|
|
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;
|
|
}
|
|
|
|
//
|
|
// Register DbContext in DI ...
|
|
if (addContext) {
|
|
dataServiceHelper.AddDbContext (
|
|
services,
|
|
connectionString,
|
|
providerType,
|
|
lifetime,
|
|
optionsBuilder
|
|
);
|
|
|
|
//
|
|
// Register Unit Of Works ...
|
|
services.Add (new ServiceDescriptor (typeof (IXUnitOfWorks<TDbContext>), typeof (XUnitOfWorks<TDbContext>), lifetime));
|
|
}
|
|
|
|
//
|
|
// 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 ...");
|
|
}
|
|
}
|
|
|
|
/// <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);
|
|
}
|
|
|
|
//
|
|
// 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
|
|
/// </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;
|
|
}
|
|
|
|
//
|
|
// 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>
|
|
/// Register Repositories on DI as Services
|
|
/// </summary>
|
|
/// <param name="services"></param>
|
|
/// <param name="config"></param>
|
|
/// <param name="lifetime"></param>
|
|
/// <param name="provider"></param>
|
|
private static void AddRepositories<TDbSeeder> (
|
|
IServiceCollection services,
|
|
IConfiguration config,
|
|
ServiceLifetime lifetime,
|
|
XDbProviders provider
|
|
)
|
|
where TDbSeeder : IXDbSeeder {
|
|
//
|
|
// Add Repositories Based On Provider Here ...
|
|
switch (provider) {
|
|
//
|
|
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:
|
|
AddMongoRepositories (services, 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);
|
|
|
|
//
|
|
// Register KeyGenerators ...
|
|
dataServiceHelper.AddKeyGenerators (services);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Do Seeding Initialization Data on DbContext
|
|
/// </summary>
|
|
/// <param name="app"></param>
|
|
private static void SeedData (
|
|
this IApplicationBuilder app
|
|
) {
|
|
//
|
|
using (var scope = app.ApplicationServices.CreateScope ()) {
|
|
//
|
|
var dbSeeder = scope.ServiceProvider.GetService<IXDbSeeder> ();
|
|
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
|
|
}
|
|
} |