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
}
}