diff --git a/MTSC/Common/Http/RoutingModules/HttpRouteBase.cs b/MTSC/Common/Http/RoutingModules/HttpRouteBase.cs index baf6670..13daeb5 100644 --- a/MTSC/Common/Http/RoutingModules/HttpRouteBase.cs +++ b/MTSC/Common/Http/RoutingModules/HttpRouteBase.cs @@ -7,8 +7,10 @@ using System.Threading.Tasks; namespace MTSC.Common.Http.RoutingModules { - public abstract class HttpRouteBase : ISetHttpContext + public abstract class HttpRouteBase : ISetHttpContext, IDisposable { + private bool disposedValue; + private static HttpResponse InternalServerError500 { get; } = new HttpResponse { @@ -19,6 +21,7 @@ namespace MTSC.Common.Http.RoutingModules public ClientData ClientData { get; private set; } public HttpRoutingHandler HttpRoutingHandler { get; private set; } public Server Server { get; private set; } + public Slim.IServiceProvider ScopedServiceProvider { get; private set; } public async Task CallHandleRequest(HttpRequest request) { @@ -38,6 +41,10 @@ namespace MTSC.Common.Http.RoutingModules } public abstract Task HandleRequest(HttpRequest request); + void ISetHttpContext.SetScopedServiceProvider(Slim.IServiceProvider serviceProvider) + { + this.ScopedServiceProvider = serviceProvider; + } void ISetHttpContext.SetClientData(ClientData clientData) { this.ClientData = clientData; @@ -50,6 +57,25 @@ namespace MTSC.Common.Http.RoutingModules { this.Server = server; } + + protected virtual void Dispose(bool disposing) + { + if (!this.disposedValue) + { + this.disposedValue = true; + if (disposing) + { + this.ScopedServiceProvider.Dispose(); + } + + this.ScopedServiceProvider = null; + } + } + + public void Dispose() + { + this.Dispose(disposing: true); + } } public abstract class HttpRouteBase : HttpRouteBase { diff --git a/MTSC/Common/Http/RoutingModules/ISetHttpContext.cs b/MTSC/Common/Http/RoutingModules/ISetHttpContext.cs index aa55f65..f89a3d9 100644 --- a/MTSC/Common/Http/RoutingModules/ISetHttpContext.cs +++ b/MTSC/Common/Http/RoutingModules/ISetHttpContext.cs @@ -1,5 +1,6 @@ using MTSC.ServerSide; using MTSC.ServerSide.Handlers; +using Slim; namespace MTSC.Common.Http.RoutingModules { @@ -8,5 +9,6 @@ namespace MTSC.Common.Http.RoutingModules void SetClientData(ClientData clientData); void SetServer(Server server); void SetHttpRoutingHandler(HttpRoutingHandler httpRoutingHandler); + void SetScopedServiceProvider(IServiceProvider serviceProvider); } } diff --git a/MTSC/Common/WebSockets/RoutingModules/ISetWebsocketContext.cs b/MTSC/Common/WebSockets/RoutingModules/ISetWebsocketContext.cs index da1d536..4739469 100644 --- a/MTSC/Common/WebSockets/RoutingModules/ISetWebsocketContext.cs +++ b/MTSC/Common/WebSockets/RoutingModules/ISetWebsocketContext.cs @@ -1,5 +1,6 @@ using MTSC.ServerSide; using MTSC.ServerSide.Handlers; +using Slim; namespace MTSC.Common.WebSockets.RoutingModules { @@ -8,5 +9,6 @@ namespace MTSC.Common.WebSockets.RoutingModules void SetServer(Server server); void SetHandler(WebsocketRoutingHandler websocketRoutingHandler); void SetClient(ClientData clientData); + void SetScopedServiceProvider(IServiceProvider serviceProvider); } } diff --git a/MTSC/Common/WebSockets/RoutingModules/WebsocketRouteBase.cs b/MTSC/Common/WebSockets/RoutingModules/WebsocketRouteBase.cs index fdf0eda..09f1fc1 100644 --- a/MTSC/Common/WebSockets/RoutingModules/WebsocketRouteBase.cs +++ b/MTSC/Common/WebSockets/RoutingModules/WebsocketRouteBase.cs @@ -6,11 +6,14 @@ using System.Text; namespace MTSC.Common.WebSockets.RoutingModules { - public abstract class WebsocketRouteBase : ISetWebsocketContext + public abstract class WebsocketRouteBase : ISetWebsocketContext, IDisposable { + private bool disposedValue; + protected Server Server { get; private set; } protected WebsocketRoutingHandler WebsocketRoutingHandler { get; private set; } protected ClientData ClientData { get; private set; } + protected Slim.IServiceProvider ScopedServiceProvider { get; private set; } public void CallConnectionInitialized() { @@ -47,6 +50,11 @@ namespace MTSC.Common.WebSockets.RoutingModules this.ClientData = clientData; } + void ISetWebsocketContext.SetScopedServiceProvider(Slim.IServiceProvider serviceProvider) + { + this.ScopedServiceProvider = serviceProvider; + } + internal static IWebsocketMessageConverter GetStringAdhocConverter() { return new AdhocConverter( @@ -74,6 +82,24 @@ namespace MTSC.Common.WebSockets.RoutingModules }; }); } + + protected virtual void Dispose(bool disposing) + { + if (!this.disposedValue) + { + this.disposedValue = true; + if (disposing) + { + this.ScopedServiceProvider.Dispose(); + this.ScopedServiceProvider = null; + } + } + } + + public void Dispose() + { + this.Dispose(disposing: true); + } } public abstract class WebsocketRouteBase : WebsocketRouteBase { diff --git a/MTSC/MTSC.csproj b/MTSC/MTSC.csproj index 8ba063e..a90b248 100644 --- a/MTSC/MTSC.csproj +++ b/MTSC/MTSC.csproj @@ -5,13 +5,13 @@ netcoreapp2.1;net48;netstandard2.0;netcoreapp3.1;net5.0 - 4.3.0 + 4.4.0 latest Alexandru-Victor Macocian MTSC Modular TCP Server and Client - 4.3.0.0 - 4.3.0.0 + 4.4.0.0 + 4.4.0.0 true AnyCPU;x64 https://github.com/AlexMacocian/MTSC @@ -29,7 +29,7 @@ - + diff --git a/MTSC/ServerSide/ClientData.cs b/MTSC/ServerSide/ClientData.cs index 0e30991..451eb81 100644 --- a/MTSC/ServerSide/ClientData.cs +++ b/MTSC/ServerSide/ClientData.cs @@ -115,31 +115,18 @@ namespace MTSC.ServerSide { if (disposing) { - // TODO: dispose managed state (managed objects). + this.SafeNetworkStream?.Dispose(); + this.SslStream?.Dispose(); + this.Resources?.Dispose(); } - this.SafeNetworkStream?.Dispose(); - this.SslStream?.Dispose(); - this.Resources?.Dispose(); - this.disposedValue = true; } } - // TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources. - // ~ClientData() - // { - // // Do not change this code. Put cleanup code in Dispose(bool disposing) above. - // Dispose(false); - // } - - // This code added to correctly implement the disposable pattern. public void Dispose() { - // Do not change this code. Put cleanup code in Dispose(bool disposing) above. this.Dispose(true); - // TODO: uncomment the following line if the finalizer is overridden above. - // GC.SuppressFinalize(this); } #endregion } diff --git a/MTSC/ServerSide/Handlers/HttpRoutingHandler.cs b/MTSC/ServerSide/Handlers/HttpRoutingHandler.cs index 1b107fb..02080b8 100644 --- a/MTSC/ServerSide/Handlers/HttpRoutingHandler.cs +++ b/MTSC/ServerSide/Handlers/HttpRoutingHandler.cs @@ -189,7 +189,8 @@ namespace MTSC.ServerSide.Handlers { if (this.TryMatchUrl(request.Method, request.RequestURI, out var urlValues, out var routeType, out var routeEnabler)) { - var module = this.GetRoute(routeType, client, server); + var scopedServiceProvider = server.ServiceManager.CreateScope(); + var module = this.GetRoute(scopedServiceProvider, routeType, client, server); if (request.Complete) { var httpRequest = request.ToRequest(); @@ -282,7 +283,7 @@ namespace MTSC.ServerSide.Handlers httpLogger.LogResponse(server, this, client, task.Result); } - this.QueueResponse(client, task.Result); + this.QueueResponse(client, task.Result); }); } catch (Exception e) @@ -339,17 +340,19 @@ namespace MTSC.ServerSide.Handlers public Func RouteEnabler { get; set; } } - private HttpRouteBase GetRoute(Type routeType, ClientData client, Server server) + private HttpRouteBase GetRoute(Slim.IServiceProvider serviceProvider, Type routeType, ClientData client, Server server) { if (!typeof(HttpRouteBase).IsAssignableFrom(routeType)) { throw new InvalidOperationException($"Cannot create new route of type {routeType.FullName}. Not of type {typeof(HttpRouteBase).FullName}"); } - var module = server.ServiceManager.GetService(routeType) as HttpRouteBase; + var module = serviceProvider.GetService(routeType) as HttpRouteBase; (module as ISetHttpContext).SetClientData(client); (module as ISetHttpContext).SetServer(server); (module as ISetHttpContext).SetHttpRoutingHandler(this); + (module as ISetHttpContext).SetScopedServiceProvider(serviceProvider); + client.Resources.SetResource(module); return module; } diff --git a/MTSC/ServerSide/Handlers/WebsocketRoutingHandler.cs b/MTSC/ServerSide/Handlers/WebsocketRoutingHandler.cs index 9fb11cb..7d2a4bd 100644 --- a/MTSC/ServerSide/Handlers/WebsocketRoutingHandler.cs +++ b/MTSC/ServerSide/Handlers/WebsocketRoutingHandler.cs @@ -189,7 +189,8 @@ namespace MTSC.ServerSide.Handlers /* * Create and assign route module to client. */ - if (server.ServiceManager.GetService(moduleType) is not WebsocketRouteBase module) + var scopedServiceManager = server.ServiceManager.CreateScope(); + if (scopedServiceManager.GetService(moduleType) is not WebsocketRouteBase module) { throw new InvalidOperationException($"Unexpected error during websocket module initialization. {moduleType.FullName} is not of type {typeof(WebsocketRouteBase).FullName}"); } @@ -197,6 +198,7 @@ namespace MTSC.ServerSide.Handlers (module as ISetWebsocketContext).SetClient(client); (module as ISetWebsocketContext).SetHandler(this); (module as ISetWebsocketContext).SetServer(server); + (module as ISetWebsocketContext).SetScopedServiceProvider(scopedServiceManager); client.Resources.SetResource(module); module.CallConnectionInitialized(); return true; @@ -304,7 +306,7 @@ namespace MTSC.ServerSide.Handlers { foreach((var routeType, _) in this.moduleDictionary.Values) { - server.ServiceManager.RegisterTransient(routeType, routeType); + server.ServiceManager.RegisterScoped(routeType, routeType); } } #endregion diff --git a/MTSC/ServerSide/ResourceDictionary.cs b/MTSC/ServerSide/ResourceDictionary.cs index 3a5ff92..19bdbe8 100644 --- a/MTSC/ServerSide/ResourceDictionary.cs +++ b/MTSC/ServerSide/ResourceDictionary.cs @@ -58,16 +58,16 @@ namespace MTSC.ServerSide { if (disposing) { - // TODO: dispose managed state (managed objects). + foreach (var value in this.Resources.Values) + { + (value as IDisposable)?.Dispose(); + } + + this.Resources.Clear(); + this.Resources = null; + } - foreach(var value in this.Resources.Values) - { - (value as IDisposable)?.Dispose(); - } - - this.Resources.Clear(); - this.Resources = null; this.disposedValue = true; } }