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