using System;
using System.Collections.Generic;
using System.IO;
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;
using xPushService.Store;
namespace xPushService.DI {
public static partial class XDIHelperExtension {
///
/// Extract Module Configuration from provided IConfiguration
///
///
/// an instance of XPushServiceConfiguration
public static XPushServiceConfiguration GetXPushServiceConfiguration (this IConfiguration config) {
//
var xPushConfigSection = config.GetSection (XPushServiceConstants.XConfigurationNodes.XPushServiceConfiguration);
return xPushConfigSection.Get ();
}
///
/// Register XPushServiceHelper ...
///
///
///
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);
}
///
/// Register Module Provided Service on DI
///
///
///
public static void AddXPushService (
this IServiceCollection services,
IConfiguration config,
ServiceLifetime lifeTime = ServiceLifetime.Singleton
) {
AddPushService (
services,
config.GetXPushServiceConfiguration (),
lifeTime
);
}
///
/// Register Module Provided Service on DI
///
///
///
public static void AddXPushService (
this IServiceCollection services,
XPushServiceConfiguration config,
ServiceLifetime lifeTime = ServiceLifetime.Singleton
) {
AddPushService (
services,
config,
lifeTime
);
}
///
/// Use Module Middlewares on Application Builder
///
///
///
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 ();
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 ();
//
// Try to Register Hubs ...
//
// Use SignalR in App ...
app.UseSignalR (routes => {
//
helper.GetHubs ().ForEach (hubDescriptor => {
//
var hubRoute = Path.Combine (config.BaseRoute, hubDescriptor.Route);
hubRoutes.Add (hubRoute);
Console.WriteLine ($"XPushService HubRoute: {hubRoute}");
//
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);
});
});
}
}
//
#region Private ...
///
/// a LogTag for XPushService ...
///
private static string XLogTag = "XPushService";
///
/// print a log in Console ...
///
///
private static void Log (string message) {
Console.WriteLine ($"{XLogTag} => {message}");
}
///
/// Register Push Service ...
///
///
///
///
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);
//
#region Try to Register Stores ...
//
var groupStore = services.GetRegisteredService ();
if (groupStore.IsNull ()) {
//
Log ($"there is no provided PushGroupStore, try to register XPushGroupInMemoryStore ...");
groupStore = new XPushGroupInMemoryStore ();
services.AddSingleton (groupStore);
}
//
var connectionStore = services.GetRegisteredService ();
if (connectionStore.IsNull ()) {
//
Log ($"there is no provided XPushConnectionStore, try to register XPushConnectionInMemoryStore ...");
connectionStore = new XPushConnectionInMemoryStore ();
services.AddSingleton (connectionStore);
}
//
var webRtcConnectionStore = services.GetRegisteredService ();
if (webRtcConnectionStore.IsNull ()) {
//
Log ($"there is no provided XWebRTCConnectionStore, try to register XWebRTCConnectionInMemoryStore ...");
webRtcConnectionStore = new XWebRTCConnectionInMemoryStore ();
services.AddSingleton (webRtcConnectionStore);
}
#endregion
//
// Register SignalR ...
var builder = services.AddSignalR ();
//
// Add NewtonSoftJson Protocol ...
builder.AddNewtonsoftJsonProtocol (x => {
x.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
x.PayloadSerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver ();
});
//
// Register XPushServiceUserNameProvider ...
services.AddSingleton ();
//
// add Message Protocol Support ...
if (config.AddSupportMessageProtocol) {
builder.AddMessagePackProtocol ();
}
}
#endregion
}
}