Files
xPushService/DI/XDIHelperExtension.cs
T
2026-05-18 00:56:30 +03:30

295 lines
9.5 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using xCommons.Extensions;
using xExceptions.Constants;
using xPushService.Configurations;
using xPushService.Constants;
using xPushService.Helpers;
using xPushService.Interfaces;
using xPushService.Providers;
namespace xPushService.DI
{
public static partial class XDIHelperExtension
{
/// <summary>
/// Extract Module Configuration from provided IConfiguration
/// </summary>
/// <param name="config"></param>
/// <returns>an instance of XPushServiceConfiguration</returns>
public static XPushServiceConfiguration GetXPushServiceConfiguration(this IConfiguration config)
{
//
var xPushConfigSection = config.GetSection(XPushServiceConstants.XConfigurationNodes.XPushServiceConfiguration);
return xPushConfigSection.Get<XPushServiceConfiguration>();
}
/// <summary>
/// Register XPushServiceHelper ...
/// </summary>
/// <param name="services"></param>
/// <param name="helper"></param>
public static void AddXPushServiceHelper(
this IServiceCollection services,
XPushServiceHelper helper
)
{
//
// Validate Args ...
if (helper.IsNull())
{
//
Log("AddXPushServiceHelper failed, helper not provided ...");
throw XException.InvalidArgs.ToException();
}
//
// Register Helper ...
services.AddSingleton(helper);
}
/// <summary>
/// Register Module Provided Service on DI
/// </summary>
/// <param name="services"></param>
/// <param name="config"></param>
public static void AddXPushService(
this IServiceCollection services,
IConfiguration config,
ServiceLifetime lifeTime = ServiceLifetime.Scoped
)
{
//
AddPushService(
services,
config.GetXPushServiceConfiguration(),
lifeTime
);
}
/// <summary>
/// Register Module Provided Service on DI
/// </summary>
/// <param name="services"></param>
/// <param name="config"></param>
public static void AddXPushService(
this IServiceCollection services,
XPushServiceConfiguration config,
ServiceLifetime lifeTime = ServiceLifetime.Scoped
)
{
//
AddPushService(
services,
config,
lifeTime
);
}
/// <summary>
/// Use Module Middlewares on Application Builder
/// </summary>
/// <param name="app"></param>
/// <param name="helper"></param>
public static void UseXPushService(
this IApplicationBuilder app,
XPushServiceHelper helper
)
{
//
// Validate Args ...
var isHelperExists = !helper.IsNull();
if (!isHelperExists)
{
//
Log("AddXPushServiceHelper failed, helper not provided ...");
throw XException.InvalidArgs.ToException();
}
//
// Create an Scope for Accessing Registered Services ...
using (var scope = app.ApplicationServices.CreateScope())
{
//
// try to Retrieve Configuration ....
var config = scope.ServiceProvider.GetService<XPushServiceConfiguration>();
if (
config.IsNull() ||
config.BaseRoute.IsNullOrEmpty() ||
config.BaseRoute.Trim().IsNullOrEmpty()
)
{
//
Log("AddXPushServiceHelper failed, Configuration not provided ...");
throw XException.InvalidConfiguration.ToException();
}
//
#region Normalize Routes ...
//
// Base Reoute ...
config.BaseRoute = config.BaseRoute.ToNormalString();
if (!config.BaseRoute.StartsWith("/"))
{
config.BaseRoute = "/" + config.BaseRoute;
}
#endregion
//
// add XPushService Hub to Helper ...
//
var hubRoutes = new List<string>();
//
// Try to Register Hubs ...
//
// Use SignalR in App ...
app.UseSignalR(routes =>
{
//
helper.GetHubs().ForEach(hubDescriptor =>
{
//
var hubRoute = config.BaseRoute + "/" + hubDescriptor.Route;
hubRoutes.Add(hubRoute);
//
try
{
//
Type routesType = routes.GetType();
MethodInfo mapHubMethod = routesType
.GetMethods()
.SingleOrDefault(m =>
m.Name == "MapHub" &&
m.GetParameters().Length == 1
);
if (mapHubMethod.IsNull())
{
throw XException.ActionFailed.ToException();
}
//
object[] genericMapHubMethodArgs = { new PathString(hubRoute) };
MethodInfo genericMapHubMethod = mapHubMethod.MakeGenericMethod(hubDescriptor.Hub);
genericMapHubMethod.Invoke(routes, genericMapHubMethodArgs);
//
Log($"Register {hubDescriptor.Hub} Hub: {hubRoute}");
}
catch
{
throw;
}
});
});
}
}
//
#region Private ...
/// <summary>
/// a LogTag for XPushService ...
/// </summary>
private static string XLogTag = "XPushService";
/// <summary>
/// print a log in Console ...
/// </summary>
/// <param name="message"></param>
private static void Log(string message)
{
Console.WriteLine($"{XLogTag} => {message}");
}
/// <summary>
/// Register Push Service ...
/// </summary>
/// <param name="services"></param>
/// <param name="config"></param>
/// <param name="lifeTime"></param>
private static void AddPushService(
IServiceCollection services,
XPushServiceConfiguration config,
ServiceLifetime lifeTime
)
{
//
#region Validate Args ...
//
var exception = XException.InvalidArgs.ToException(); ;
//
// Services ...
var isServicesExists = !services.IsNull();
if (!isServicesExists)
{
//
Log("AddXPushServiceHelper failed, services not provided ...");
throw exception;
}
//
// Config ...
var isConfigExists = !config.IsNull();
if (!isConfigExists)
{
//
Log("AddXPushServiceHelper failed, configuration not provided ...");
throw exception;
}
//
// Lifetime ...
var isLifetimeExists = !lifeTime.IsNull();
if (!isLifetimeExists)
{
//
Log("AddXPushServiceHelper failed, lifetime not provided ...");
throw exception;
}
#endregion
//
// Register XPushService Configuration ...
services.AddSingleton(config);
//
// Register SignalR ...
var builder = services.AddSignalR(options =>
{
options.KeepAliveInterval = TimeSpan.FromSeconds(10);
options.ClientTimeoutInterval = TimeSpan.FromSeconds(10);
});
//
// Add NewtonSoftJson Protocol ...
builder.AddNewtonsoftJsonProtocol(x =>
{
x.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
x.PayloadSerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
});
//
// Register XPushServiceUserNameProvider ...
services.AddSingleton<IUserIdProvider, XPushServiceUserNameProvider>();
//
// add Message Protocol Support ...
if (config.AddSupportMessageProtocol)
{
builder.AddMessagePackProtocol();
}
}
#endregion
}
}