Initial Commit ...
This commit is contained in:
@@ -0,0 +1,622 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user