From 50fd3e7b7382d5c071a9520030581777c79766e8 Mon Sep 17 00:00:00 2001 From: Mikhail Mitrofanov Date: Thu, 20 Feb 2025 16:10:09 +0300 Subject: [PATCH] =?UTF-8?q?=D0=B1=D0=B8=D0=BB=D0=B4=D0=B8=D1=82=D1=81?= =?UTF-8?q?=D1=8F=20=D0=BD=D0=B0=20=D1=81=D1=82=D0=B0=D1=80=D0=BE=D0=BC=20?= =?UTF-8?q?=D0=B4=D0=BE=D1=82=D0=BD=D0=B5=D1=82=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Example.Backend/Example.Backend.csproj | 6 +- Example.Backend/LoadTestImp.cs | 40 +- Example.Backend/Page.cs | 13 +- Example.Backend/Printer.cs | 26 +- Example.Backend/PrinterFactory.cs | 60 ++- Example.Backend/Program.cs | 64 +-- Example.Frontend/ClientBasedPrinter.cs | 42 +- Example.Frontend/Example.Frontend.csproj | 6 +- Example.Frontend/Program.cs | 114 ++-- Example.Shared/Example.Shared.csproj | 6 +- Example.Shared/ILoadTest.cs | 17 +- Example.Shared/IPage.cs | 11 +- Example.Shared/IPrinter.cs | 15 +- Example.Shared/IPrinterFactory.cs | 19 +- mROA.Benchmark/Program.cs | 80 +-- mROA.Benchmark/mROA.Benchmark.csproj | 4 +- mROA.Codegen/mROA.Codegen.csproj | 3 +- mROA.Codegen/mROASourceGenerator.cs | 488 ++++++++++-------- mROA.Test/NextGenTest.cs | 120 ++--- mROA.Test/mROA.Test.csproj | 4 +- mROA/Abstract/ICommandExecution.cs | 13 +- mROA/Abstract/IConnectionHub.cs | 21 +- mROA/Abstract/IContextRepository.cs | 19 +- mROA/Abstract/IContextRepositoryHub.cs | 9 +- mROA/Abstract/IExecuteModule.cs | 9 +- mROA/Abstract/IFrontendBridge.cs | 10 +- mROA/Abstract/IGatewayModule.cs | 11 +- mROA/Abstract/IIdentityGenerator.cs | 9 +- mROA/Abstract/IInjectableModule.cs | 9 +- mROA/Abstract/IInteractionModule.cs | 24 +- mROA/Abstract/IMethodRepository.cs | 16 +- mROA/Abstract/IOwnershipRepository.cs | 11 +- .../Abstract/IRepresentationModuleProducer.cs | 9 +- mROA/Abstract/IRequestExtractor.cs | 9 +- mROA/Abstract/ISerialisationModule.cs | 47 +- mROA/Abstract/ISerializationToolkit.cs | 23 +- .../SharedObjectInterfaceAttribute.cs | 7 +- .../SharedObjectSingletonAttribute.cs | 7 +- .../Backend/BackendIdentityGenerator.cs | 23 +- .../Backend/BasicConfigurationExtensions.cs | 50 +- .../Backend/BasicExecutionModule.cs | 197 +++---- mROA/Implementation/Backend/ConnectionHub.cs | 55 +- .../Backend/ContextRepository.cs | 150 +++--- .../Backend/HubRequestExtractor.cs | 92 ++-- .../Backend/MultiClientContextRepository.cs | 93 ++-- .../Backend/MultiClientOwnershipRepository.cs | 43 +- .../Backend/NetworkGatewayModule.cs | 148 +++--- .../Bootstrap/FullMixBuilder.cs | 29 +- mROA/Implementation/CallRequest.cs | 36 +- .../ExceptionCommandExecution.cs | 24 +- .../CommandExecution/FinalCommandExecution.cs | 28 +- .../TypedFinalCommandExecution.cs | 16 +- .../CreativeRepresentationModuleProducer.cs | 58 ++- .../JsonFrontendSerialisationModule.cs | 22 +- .../Frontend/NetworkFrontendBridge.cs | 68 +-- .../Frontend/RequestExtractor.cs | 146 +++--- .../Frontend/StaticOwnershipRepository.cs | 26 +- mROA/Implementation/IdAssingnment.cs | 9 +- .../JsonSerializationToolkit.cs | 100 ++-- mROA/Implementation/MethodRepository.cs | 70 +-- mROA/Implementation/NetworkMessage.cs | 26 +- .../NextGenerationInteractionModule.cs | 168 +++--- .../Implementation/RemoteContextRepository.cs | 98 ++-- mROA/Implementation/RemoteObjectBase.cs | 85 +-- mROA/Implementation/RepresentationModule.cs | 161 +++--- mROA/Implementation/SharedObject.cs | 160 +++--- .../StaticRepresentationModuleProducer.cs | 32 +- mROA/LegacyExtentions.cs | 43 ++ mROA/mROA.csproj | 8 +- 69 files changed, 1990 insertions(+), 1675 deletions(-) create mode 100644 mROA/LegacyExtentions.cs diff --git a/Example.Backend/Example.Backend.csproj b/Example.Backend/Example.Backend.csproj index 62581cc..fc4e81b 100644 --- a/Example.Backend/Example.Backend.csproj +++ b/Example.Backend/Example.Backend.csproj @@ -2,9 +2,11 @@ Exe - net9.0 - enable + netstandard2.1 + enable + + 9 diff --git a/Example.Backend/LoadTestImp.cs b/Example.Backend/LoadTestImp.cs index e0ea125..bc22304 100644 --- a/Example.Backend/LoadTestImp.cs +++ b/Example.Backend/LoadTestImp.cs @@ -1,28 +1,30 @@ -using Example.Shared; +using System; +using Example.Shared; using mROA.Implementation.Attributes; -namespace Example.Backend; - -[SharedObjectSingleton] -public class LoadTestImp : ILoadTest +namespace Example.Backend { - public int Next(int last) + [SharedObjectSingleton] + public class LoadTestImp : ILoadTest { - return last + 1; - } + public int Next(int last) + { + return last + 1; + } - public int Last(int next) - { - return next - 1; - } + public int Last(int next) + { + return next - 1; + } - public void C() - { - throw new NotImplementedException(); - } + public void C() + { + throw new NotImplementedException(); + } - public void A() - { - throw new NotImplementedException(); + public void A() + { + throw new NotImplementedException(); + } } } \ No newline at end of file diff --git a/Example.Backend/Page.cs b/Example.Backend/Page.cs index a635f09..7e2fb4d 100644 --- a/Example.Backend/Page.cs +++ b/Example.Backend/Page.cs @@ -1,13 +1,14 @@ using System.Text; using Example.Shared; -namespace Example.Backend; - -public class Page : IPage +namespace Example.Backend { - public string Text; - public byte[] GetData() + public class Page : IPage { - return Encoding.UTF8.GetBytes(Text); + public string Text; + public byte[] GetData() + { + return Encoding.UTF8.GetBytes(Text); + } } } \ No newline at end of file diff --git a/Example.Backend/Printer.cs b/Example.Backend/Printer.cs index b456160..59ef144 100644 --- a/Example.Backend/Printer.cs +++ b/Example.Backend/Printer.cs @@ -1,20 +1,22 @@ +using System.Threading; +using System.Threading.Tasks; using Example.Shared; using mROA.Implementation; -namespace Example.Backend; - - -public class Printer : IPrinter +namespace Example.Backend { - public string Name; - public string GetName() + public class Printer : IPrinter { - return Name; - } + public string Name; + public string GetName() + { + return Name; + } - public async Task> Print(string text, CancellationToken cancellationToken = default) - { - // throw new Exception("The method or operation is not implemented."); - return new Page {Text = text}; + public async Task> Print(string text, CancellationToken cancellationToken = default) + { + // throw new Exception("The method or operation is not implemented."); + return new Page {Text = text}; + } } } \ No newline at end of file diff --git a/Example.Backend/PrinterFactory.cs b/Example.Backend/PrinterFactory.cs index e71503f..697b2e4 100644 --- a/Example.Backend/PrinterFactory.cs +++ b/Example.Backend/PrinterFactory.cs @@ -1,40 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; using Example.Shared; using mROA.Implementation; using mROA.Implementation.Attributes; -namespace Example.Backend; - -[SharedObjectSingleton] -public class PrinterFactory : IPrinterFactory +namespace Example.Backend { - private List _printers = new(); - - public SharedObject Create(string printerName) + [SharedObjectSingleton] + public class PrinterFactory : IPrinterFactory { - Console.WriteLine("Creating printer"); - return new Printer { Name = printerName }; - } + private List _printers = new List(); - public void Register(SharedObject printer) - { - _printers.Add(printer.Value); - Console.WriteLine("Registered printer"); - } + public SharedObject Create(string printerName) + { + Console.WriteLine("Creating printer"); + return new Printer { Name = printerName }; + } - public SharedObject GetPrinterByName(string printerName) - { - Console.WriteLine("Getting printer"); - return new SharedObject(_printers.Find(i => i.GetName() == printerName)!); - } + public void Register(SharedObject printer) + { + _printers.Add(printer.Value); + Console.WriteLine("Registered printer"); + } - public SharedObject GetFirstPrinter() - { - return new SharedObject(_printers.First()); - } + public SharedObject GetPrinterByName(string printerName) + { + Console.WriteLine("Getting printer"); + return new SharedObject(_printers.Find(i => i.GetName() == printerName)!); + } - public string[] CollectAllNames() - { - Console.WriteLine("Collecting all printers"); - return _printers.Select(i => i.GetName()).ToArray(); + public SharedObject GetFirstPrinter() + { + return new SharedObject(_printers.First()); + } + + public string[] CollectAllNames() + { + Console.WriteLine("Collecting all printers"); + return _printers.Select(i => i.GetName()).ToArray(); + } } } \ No newline at end of file diff --git a/Example.Backend/Program.cs b/Example.Backend/Program.cs index 65c6fbf..0a8315a 100644 --- a/Example.Backend/Program.cs +++ b/Example.Backend/Program.cs @@ -7,37 +7,43 @@ using mROA.Implementation.Backend; using mROA.Implementation.Bootstrap; using mROA.Implementation.Frontend; - -var builder = new FullMixBuilder(); -builder.UseJsonSerialisation(); -builder.Modules.Add(new BackendIdentityGenerator()); -builder.UseNetworkGateway(new IPEndPoint(IPAddress.Loopback, 4567), typeof(NextGenerationInteractionModule), - builder.GetModule()!); - -builder.Modules.Add(new ConnectionHub()); -builder.Modules.Add(new HubRequestExtractor(typeof(RequestExtractor))); - -builder.UseBasicExecution(); - -builder.Modules.Add(new RemoteContextRepository()); -// builder.UseCollectableContextRepository(typeof(PrinterFactory).Assembly); -builder.Modules.Add(new MultiClientContextRepository(i => +class Program { - var repo = new ContextRepository(); - repo.FillSingletons(typeof(PrinterFactory).Assembly); - return repo; -})); -builder.SetupMethodsRepository(new CoCodegenMethodRepository()); -builder.Modules.Add(new CreativeRepresentationModuleProducer([builder.GetModule()!], - typeof(RepresentationModule))); + public static void Main(string[] args) + { + var builder = new FullMixBuilder(); + builder.UseJsonSerialisation(); + builder.Modules.Add(new BackendIdentityGenerator()); + builder.UseNetworkGateway(new IPEndPoint(IPAddress.Loopback, 4567), typeof(NextGenerationInteractionModule), + builder.GetModule()!); -builder.Build(); -new RemoteTypeBinder(); + builder.Modules.Add(new ConnectionHub()); + builder.Modules.Add(new HubRequestExtractor(typeof(RequestExtractor))); -TransmissionConfig.RealContextRepository = builder.GetModule(); -TransmissionConfig.RemoteEndpointContextRepository = builder.GetModule(); -TransmissionConfig.OwnershipRepository = new MultiClientOwnershipRepository(); + builder.UseBasicExecution(); -var gateway = builder.GetModule(); + builder.Modules.Add(new RemoteContextRepository()); +// builder.UseCollectableContextRepository(typeof(PrinterFactory).Assembly); + builder.Modules.Add(new MultiClientContextRepository(i => + { + var repo = new ContextRepository(); + repo.FillSingletons(typeof(PrinterFactory).Assembly); + return repo; + })); + builder.SetupMethodsRepository(new CoCodegenMethodRepository()); + builder.Modules.Add(new CreativeRepresentationModuleProducer( + new IInjectableModule[] { builder.GetModule()! }, + typeof(RepresentationModule))); -gateway.Run(); \ No newline at end of file + builder.Build(); + new RemoteTypeBinder(); + + TransmissionConfig.RealContextRepository = builder.GetModule(); + TransmissionConfig.RemoteEndpointContextRepository = builder.GetModule(); + TransmissionConfig.OwnershipRepository = new MultiClientOwnershipRepository(); + + var gateway = builder.GetModule(); + + gateway.Run(); + } +} \ No newline at end of file diff --git a/Example.Frontend/ClientBasedPrinter.cs b/Example.Frontend/ClientBasedPrinter.cs index 58a97c8..32c3de0 100644 --- a/Example.Frontend/ClientBasedPrinter.cs +++ b/Example.Frontend/ClientBasedPrinter.cs @@ -1,28 +1,32 @@ -using Example.Shared; +using System; +using System.Threading; +using System.Threading.Tasks; +using Example.Shared; using mROA.Implementation; -namespace Example.Frontend; - -public class ClientBasedPrinter : IPrinter +namespace Example.Frontend { - public string GetName() + public class ClientBasedPrinter : IPrinter { - Console.WriteLine("ClientBasedPrinter called from server!!!!!!!!!!! Vova likes that:)"); - return "ClientBasedPrinter from mroa"; + public string GetName() + { + Console.WriteLine("ClientBasedPrinter called from server!!!!!!!!!!! Vova likes that:)"); + return "ClientBasedPrinter from mroa"; + } + + public async Task> Print(string text, CancellationToken cancellationToken) + { + Console.WriteLine($"Printed: {text}"); + await Task.Yield(); + return new ClientBasedPage(); + } } - public async Task> Print(string text, CancellationToken cancellationToken) + public class ClientBasedPage : IPage { - Console.WriteLine($"Printed: {text}"); - await Task.Yield(); - return new ClientBasedPage(); - } -} - -public class ClientBasedPage : IPage -{ - public byte[] GetData() - { - return [1, 2, 3]; + public byte[] GetData() + { + return new byte[] { 1, 2, 3 }; + } } } \ No newline at end of file diff --git a/Example.Frontend/Example.Frontend.csproj b/Example.Frontend/Example.Frontend.csproj index f59d7cc..e4d8f0d 100644 --- a/Example.Frontend/Example.Frontend.csproj +++ b/Example.Frontend/Example.Frontend.csproj @@ -2,9 +2,11 @@ Exe - net9.0 - enable + netstandard2.1 + enable + + 9 diff --git a/Example.Frontend/Program.cs b/Example.Frontend/Program.cs index fdbd77d..ca2ac99 100644 --- a/Example.Frontend/Program.cs +++ b/Example.Frontend/Program.cs @@ -1,6 +1,8 @@ -using System.Diagnostics; +using System; +using System.Diagnostics; using System.Net; using System.Text; +using System.Threading; using Example.Frontend; using Example.Shared; using mROA.Codegen; @@ -9,71 +11,77 @@ using mROA.Implementation.Backend; using mROA.Implementation.Bootstrap; using mROA.Implementation.Frontend; -var builder = new FullMixBuilder(); -new RemoteTypeBinder(); -builder.Modules.Add(new JsonSerializationToolkit()); -builder.Modules.Add(new RemoteContextRepository()); -builder.Modules.Add(new NextGenerationInteractionModule()); -builder.Modules.Add(new RepresentationModule()); -builder.Modules.Add(new NetworkFrontendBridge(new IPEndPoint(IPAddress.Loopback, 4567))); -builder.Modules.Add(new StaticRepresentationModuleProducer()); -builder.Modules.Add(new RequestExtractor()); -builder.Modules.Add(new BasicExecutionModule()); -builder.Modules.Add(new CoCodegenMethodRepository()); -builder.UseCollectableContextRepository(); -builder.Build(); +class Program +{ + public static void Main(string[] args) + { + var builder = new FullMixBuilder(); + new RemoteTypeBinder(); + builder.Modules.Add(new JsonSerializationToolkit()); + builder.Modules.Add(new RemoteContextRepository()); + builder.Modules.Add(new NextGenerationInteractionModule()); + builder.Modules.Add(new RepresentationModule()); + builder.Modules.Add(new NetworkFrontendBridge(new IPEndPoint(IPAddress.Loopback, 4567))); + builder.Modules.Add(new StaticRepresentationModuleProducer()); + builder.Modules.Add(new RequestExtractor()); + builder.Modules.Add(new BasicExecutionModule()); + builder.Modules.Add(new CoCodegenMethodRepository()); + builder.UseCollectableContextRepository(); + builder.Build(); -TransmissionConfig.RealContextRepository = builder.GetModule(); -TransmissionConfig.RemoteEndpointContextRepository = builder.GetModule(); + TransmissionConfig.RealContextRepository = builder.GetModule(); + TransmissionConfig.RemoteEndpointContextRepository = builder.GetModule(); -builder.GetModule()!.Connect(); -_ = builder.GetModule()!.StartExtraction(); -Console.WriteLine(TransmissionConfig.OwnershipRepository.GetOwnershipId()); -var context = builder.GetModule(); + builder.GetModule()!.Connect(); + _ = builder.GetModule()!.StartExtraction(); + Console.WriteLine(TransmissionConfig.OwnershipRepository.GetOwnershipId()); + var context = builder.GetModule(); -var factory = context.GetSingleObject(typeof(IPrinterFactory)) as IPrinterFactory; + var factory = context.GetSingleObject(typeof(IPrinterFactory)) as IPrinterFactory; //правильный порядок команд 8-5-10-7 -var printer = factory.Create("Test"); -Console.WriteLine("Printer created"); -Thread.Sleep(100); + var printer = factory.Create("Test"); + Console.WriteLine("Printer created"); + Thread.Sleep(100); -var name = printer.Value.GetName(); -Console.WriteLine("Printer name : {0}", name); -Thread.Sleep(100); + var name = printer.Value.GetName(); + Console.WriteLine("Printer name : {0}", name); + Thread.Sleep(100); -factory.Register(new SharedObject(new ClientBasedPrinter())); -Console.WriteLine("Registered printer"); -Thread.Sleep(100); + factory.Register(new SharedObject(new ClientBasedPrinter())); + Console.WriteLine("Registered printer"); + Thread.Sleep(100); -var registred = factory.GetFirstPrinter(); -Console.WriteLine("First printer"); -Thread.Sleep(100); + var registred = factory.GetFirstPrinter(); + Console.WriteLine("First printer"); + Thread.Sleep(100); -Console.WriteLine(registred.Value); -Console.WriteLine("Collecting all printers"); -var names = factory.CollectAllNames(); -Thread.Sleep(100); + Console.WriteLine(registred.Value); + Console.WriteLine("Collecting all printers"); + var names = factory.CollectAllNames(); + Thread.Sleep(100); -Console.WriteLine(string.Join(", ", names)); + Console.WriteLine(string.Join(", ", names)); -var page = printer.Value.Print("Test Page", new CancellationToken()).GetAwaiter().GetResult(); -var data = page.Value.GetData(); -Console.WriteLine("Data : {0}", Encoding.UTF8.GetString(data)); + var page = printer.Value.Print("Test Page", new CancellationToken()).GetAwaiter().GetResult(); + var data = page.Value.GetData(); + Console.WriteLine("Data : {0}", Encoding.UTF8.GetString(data)); -var loadSingleton = context.GetSingleObject(typeof(ILoadTest)) as ILoadTest; + var loadSingleton = context.GetSingleObject(typeof(ILoadTest)) as ILoadTest; -const int iterations = 10000; -var timer = Stopwatch.StartNew(); -var x = 0; -for (int i = 0; i < iterations; i++) -{ - x = loadSingleton.Next(x); -} + const int iterations = 10000; + var timer = Stopwatch.StartNew(); + var x = 0; + for (int i = 0; i < iterations; i++) + { + x = loadSingleton.Next(x); + } -timer.Stop(); -Console.WriteLine("X is {0}", x); -Console.WriteLine("Time : {0}", timer.Elapsed.TotalMilliseconds); -Console.WriteLine($"Time per call: {timer.Elapsed.TotalMilliseconds / iterations} ms"); \ No newline at end of file + timer.Stop(); + Console.WriteLine("X is {0}", x); + Console.WriteLine("Time : {0}", timer.Elapsed.TotalMilliseconds); + Console.WriteLine($"Time per call: {timer.Elapsed.TotalMilliseconds / iterations} ms"); + } +} \ No newline at end of file diff --git a/Example.Shared/Example.Shared.csproj b/Example.Shared/Example.Shared.csproj index 40f085d..37ad63a 100644 --- a/Example.Shared/Example.Shared.csproj +++ b/Example.Shared/Example.Shared.csproj @@ -1,9 +1,11 @@  - net9.0 - enable + netstandard2.1 + enable + + 9 diff --git a/Example.Shared/ILoadTest.cs b/Example.Shared/ILoadTest.cs index dc4e787..326822f 100644 --- a/Example.Shared/ILoadTest.cs +++ b/Example.Shared/ILoadTest.cs @@ -1,13 +1,14 @@ using mROA.Implementation.Attributes; -namespace Example.Shared; - -[SharedObjectInterface] -public interface ILoadTest +namespace Example.Shared { - int Next(int last); - int Last(int next); - void C(); - void A(); + [SharedObjectInterface] + public interface ILoadTest + { + int Next(int last); + int Last(int next); + void C(); + void A(); + } } diff --git a/Example.Shared/IPage.cs b/Example.Shared/IPage.cs index 6f39f19..a8d21f9 100644 --- a/Example.Shared/IPage.cs +++ b/Example.Shared/IPage.cs @@ -1,9 +1,10 @@ using mROA.Implementation.Attributes; -namespace Example.Shared; - -[SharedObjectInterface] -public interface IPage +namespace Example.Shared { - byte[] GetData(); + [SharedObjectInterface] + public interface IPage + { + byte[] GetData(); + } } \ No newline at end of file diff --git a/Example.Shared/IPrinter.cs b/Example.Shared/IPrinter.cs index 2d8e6c8..a2c789f 100644 --- a/Example.Shared/IPrinter.cs +++ b/Example.Shared/IPrinter.cs @@ -1,12 +1,15 @@ +using System.Threading; +using System.Threading.Tasks; using mROA.Implementation; using mROA.Implementation.Attributes; -namespace Example.Shared; - -[SharedObjectInterface] -public interface IPrinter +namespace Example.Shared { - string GetName(); - Task> Print(string text, CancellationToken cancellationToken); + [SharedObjectInterface] + public interface IPrinter + { + string GetName(); + Task> Print(string text, CancellationToken cancellationToken); + } } \ No newline at end of file diff --git a/Example.Shared/IPrinterFactory.cs b/Example.Shared/IPrinterFactory.cs index eb6ee8e..bc18270 100644 --- a/Example.Shared/IPrinterFactory.cs +++ b/Example.Shared/IPrinterFactory.cs @@ -1,15 +1,16 @@ using mROA.Implementation; using mROA.Implementation.Attributes; -namespace Example.Shared; - -[SharedObjectInterface] -public interface IPrinterFactory +namespace Example.Shared { - SharedObject Create(string printerName); - void Register(SharedObject printer); - SharedObject GetPrinterByName(string printerName); - SharedObject GetFirstPrinter(); - string[] CollectAllNames(); + [SharedObjectInterface] + public interface IPrinterFactory + { + SharedObject Create(string printerName); + void Register(SharedObject printer); + SharedObject GetPrinterByName(string printerName); + SharedObject GetFirstPrinter(); + string[] CollectAllNames(); + } } \ No newline at end of file diff --git a/mROA.Benchmark/Program.cs b/mROA.Benchmark/Program.cs index 57ab0c3..c4ebb5e 100644 --- a/mROA.Benchmark/Program.cs +++ b/mROA.Benchmark/Program.cs @@ -1,50 +1,54 @@ -using BenchmarkDotNet.Attributes; +using System; +using System.Collections.Generic; +using System.Linq; +using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Running; -namespace mROA.Benchmark; - -class Program +namespace mROA.Benchmark { - static void Main(string[] args) + class Program { - Console.WriteLine("Hello, World!"); - var summary = BenchmarkRunner.Run(); - - } -} - -public class CollectionsSpeed -{ - private const int N = 1000; - - private readonly List _immutable; - private readonly int[] _array; - - public CollectionsSpeed() - { - _array = Enumerable.Range(0, N).ToArray(); - _immutable = [.._array]; - } - - [Benchmark] - public int DefaultArray() - { - var sum = 0; - for (int i = 0; i < N; i++) + static void Main(string[] args) { - sum += _array[i]; + Console.WriteLine("Hello, World!"); + var summary = BenchmarkRunner.Run(); + } - return sum; } - - [Benchmark] - public int ImmutableArray() + + public class CollectionsSpeed { - var sum = 0; - for (int i = 0; i < N; i++) + private const int N = 1000; + + private readonly List _immutable; + private readonly int[] _array; + + public CollectionsSpeed() { - sum += _immutable[i]; + _array = Enumerable.Range(0, N).ToArray(); + _immutable = [.._array]; + } + + [Benchmark] + public int DefaultArray() + { + var sum = 0; + for (int i = 0; i < N; i++) + { + sum += _array[i]; + } + return sum; + } + + [Benchmark] + public int ImmutableArray() + { + var sum = 0; + for (int i = 0; i < N; i++) + { + sum += _immutable[i]; + } + return sum; } - return sum; } } \ No newline at end of file diff --git a/mROA.Benchmark/mROA.Benchmark.csproj b/mROA.Benchmark/mROA.Benchmark.csproj index 78eb323..5697c66 100644 --- a/mROA.Benchmark/mROA.Benchmark.csproj +++ b/mROA.Benchmark/mROA.Benchmark.csproj @@ -2,8 +2,8 @@ Exe - net9.0 - enable + netstandard2.1 + enable diff --git a/mROA.Codegen/mROA.Codegen.csproj b/mROA.Codegen/mROA.Codegen.csproj index 0b8cdea..2a23fd6 100644 --- a/mROA.Codegen/mROA.Codegen.csproj +++ b/mROA.Codegen/mROA.Codegen.csproj @@ -25,8 +25,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - + diff --git a/mROA.Codegen/mROASourceGenerator.cs b/mROA.Codegen/mROASourceGenerator.cs index da1f1bb..db252ae 100644 --- a/mROA.Codegen/mROASourceGenerator.cs +++ b/mROA.Codegen/mROASourceGenerator.cs @@ -7,19 +7,19 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -namespace mROA.Codegen; - -/// -/// A sample source generator that creates a custom report based on class properties. The target class should be annotated with the 'Generators.ReportAttribute' attribute. -/// When using the source code as a baseline, an incremental source generator is preferable because it reduces the performance overhead. -/// -[Generator] -public class mROASourceGenerator : IIncrementalGenerator +namespace mROA.Codegen { - private const string Namespace = "mROA.Implementation"; - private const string AttributeName = "SharedObjectInterafceAttribute"; + /// + /// A sample source generator that creates a custom report based on class properties. The target class should be annotated with the 'Generators.ReportAttribute' attribute. + /// When using the source code as a baseline, an incremental source generator is preferable because it reduces the performance overhead. + /// + [Generator] + public class mROASourceGenerator : ISourceGenerator + { + private const string Namespace = "mROA.Implementation"; + private const string AttributeName = "SharedObjectInterafceAttribute"; - private const string AttributeSourceCode = $@"// + private const string AttributeSourceCode = $@"// namespace {Namespace} {{ @@ -29,151 +29,151 @@ namespace {Namespace} }} }}"; - public void Initialize(IncrementalGeneratorInitializationContext context) - { - // Filter classes annotated with the [Report] attribute. Only filtered Syntax Nodes can trigger code generation. - var provider = context.SyntaxProvider - .CreateSyntaxProvider( - (s, _) => s is InterfaceDeclarationSyntax, - (ctx, _) => GetClassDeclarationForSourceGen(ctx)) - .Where(t => t.reportAttributeFound) - .Select((t, _) => t.Item1); + // public void Initialize(IncrementalGeneratorInitializationContext context) + // { + // // Filter classes annotated with the [Report] attribute. Only filtered Syntax Nodes can trigger code generation. + // var provider = context.SyntaxProvider + // .CreateSyntaxProvider( + // (s, _) => s is InterfaceDeclarationSyntax, + // (ctx, _) => GetClassDeclarationForSourceGen(ctx)) + // .Where(t => t.reportAttributeFound) + // .Select((t, _) => t.Item1); + // + // // Generate the source code. + // context.RegisterSourceOutput(context.CompilationProvider.Combine(provider.Collect()), + // ((ctx, t) => GenerateCode(ctx, t.Left, t.Right))); + // } - // Generate the source code. - context.RegisterSourceOutput(context.CompilationProvider.Combine(provider.Collect()), - ((ctx, t) => GenerateCode(ctx, t.Left, t.Right))); - } + /// + /// Checks whether the Node is annotated with the [Report] attribute and maps syntax context to the specific node type (ClassDeclarationSyntax). + /// + /// Syntax context, based on CreateSyntaxProvider predicate + /// The specific cast and whether the attribute was found. + // private static (InterfaceDeclarationSyntax, bool reportAttributeFound) GetClassDeclarationForSourceGen( + // GeneratorSyntaxContext context) + // { + // var classDeclarationSyntax = (InterfaceDeclarationSyntax)context.Node; + // + // // Go through all attributes of the class. + // foreach (AttributeListSyntax attributeListSyntax in classDeclarationSyntax.AttributeLists) + // foreach (AttributeSyntax attributeSyntax in attributeListSyntax.Attributes) + // { + // if (context.SemanticModel.GetSymbolInfo(attributeSyntax).Symbol is not IMethodSymbol attributeSymbol) + // continue; // if we can't get the symbol, ignore it + // + // string attributeName = attributeSymbol.ContainingType.ToDisplayString(); + // + // // Check the full name of the [Report] attribute. + // if (attributeName == "mROA.Implementation.Attributes.SharedObjectInterfaceAttribute") + // return (classDeclarationSyntax, true); + // } + // + // return (classDeclarationSyntax, false); + // } - /// - /// Checks whether the Node is annotated with the [Report] attribute and maps syntax context to the specific node type (ClassDeclarationSyntax). - /// - /// Syntax context, based on CreateSyntaxProvider predicate - /// The specific cast and whether the attribute was found. - private static (InterfaceDeclarationSyntax, bool reportAttributeFound) GetClassDeclarationForSourceGen( - GeneratorSyntaxContext context) - { - var classDeclarationSyntax = (InterfaceDeclarationSyntax)context.Node; - - // Go through all attributes of the class. - foreach (AttributeListSyntax attributeListSyntax in classDeclarationSyntax.AttributeLists) - foreach (AttributeSyntax attributeSyntax in attributeListSyntax.Attributes) + /// + /// Generate code action. + /// It will be executed on specific nodes (ClassDeclarationSyntax annotated with the [Report] attribute) changed by the user. + /// + /// Source generation context used to add source files. + /// Compilation used to provide access to the Semantic Model. + /// Nodes annotated with the [Report] attribute that trigger the generate action. + private void GenerateCode(GeneratorExecutionContext context, Compilation compilation, + ImmutableArray classes) { - if (context.SemanticModel.GetSymbolInfo(attributeSyntax).Symbol is not IMethodSymbol attributeSymbol) - continue; // if we can't get the symbol, ignore it - - string attributeName = attributeSymbol.ContainingType.ToDisplayString(); - - // Check the full name of the [Report] attribute. - if (attributeName == "mROA.Implementation.Attributes.SharedObjectInterfaceAttribute") - return (classDeclarationSyntax, true); - } - - return (classDeclarationSyntax, false); - } - - /// - /// Generate code action. - /// It will be executed on specific nodes (ClassDeclarationSyntax annotated with the [Report] attribute) changed by the user. - /// - /// Source generation context used to add source files. - /// Compilation used to provide access to the Semantic Model. - /// Nodes annotated with the [Report] attribute that trigger the generate action. - private void GenerateCode(SourceProductionContext context, Compilation compilation, - ImmutableArray classes) - { - var methods = new List<(string, IMethodSymbol)>(); - var frontendContextRepo = new List(); - // Go through all filtered class declarations. - var declarations = classes.ToList().OrderBy(i => i.Identifier.Text).ToList(); - foreach (var classDeclarationSyntax in declarations) - { - // We need to get semantic model of the class to retrieve metadata. - var semanticModel = compilation.GetSemanticModel(classDeclarationSyntax.SyntaxTree); - - - // Symbols allow us to get the compile-time information. - if (semanticModel.GetDeclaredSymbol(classDeclarationSyntax) is not INamedTypeSymbol classSymbol) - continue; - - - var namespaceName = classSymbol.ContainingNamespace.ToDisplayString(); - - // 'Identifier' means the token of the node. Get class name from the syntax node. - var className = classDeclarationSyntax.Identifier.Text; - - // Go through all class members with a particular type (property) to generate method lines. - var methodBody = classSymbol.GetMembers() - .OfType().OrderBy(i => i.Name); - - var originalName = className; - // Build up the source code - className = className.TrimStart('I') + "RemoteEndpoint"; - - - var methodsText = new List(); - - foreach (var method in methodBody) + var methods = new List<(string, IMethodSymbol)>(); + var frontendContextRepo = new List(); + // Go through all filtered class declarations. + var declarations = classes.ToList().OrderBy(i => i.Identifier.Text).ToList(); + foreach (var classDeclarationSyntax in declarations) { - var index = methods.Count; - methods.Add((namespaceName + "." + originalName, method)); - var sb = new StringBuilder(); + // We need to get semantic model of the class to retrieve metadata. + var semanticModel = compilation.GetSemanticModel(classDeclarationSyntax.SyntaxTree); - bool isAsync = method.ReturnType.Name == "Task"; - bool isVoid = method.ReturnType.Name == "Void" || method.ReturnType.ToString() == "Task"; - bool isParametrized = method.Parameters.Length == 1 && !isAsync || - method.Parameters.Length == 2 && isAsync; + // Symbols allow us to get the compile-time information. + if (semanticModel.GetDeclaredSymbol(classDeclarationSyntax) is not INamedTypeSymbol classSymbol) + continue; - //Creating signature - sb.AppendLine("public" + (isAsync - ? " async " - : " ") + - $"{method.ReturnType.ToDisplayString()} {method.Name}({string.Join(", ", method.Parameters.Select(ToFullString))}){{"); + var namespaceName = classSymbol.ContainingNamespace.ToDisplayString(); + + // 'Identifier' means the token of the node. Get class name from the syntax node. + var className = classDeclarationSyntax.Identifier.Text; + + // Go through all class members with a particular type (property) to generate method lines. + var methodBody = classSymbol.GetMembers() + .OfType().OrderBy(i => i.Name); + + var originalName = className; + // Build up the source code + className = className.TrimStart('I') + "RemoteEndpoint"; - var prefix = isAsync ? "await " : ""; - var postfix = !isAsync ? (isVoid? ".Wait()" : ".GetAwaiter().GetResult()") : ""; - var parameterLink = isParametrized ? ", " + method.Parameters.First().Name : string.Empty; - var caller = isVoid ? $"CallAsync({index}{parameterLink})" : - isAsync ? $"GetResultAsync<{ExtractTaskType(method.ReturnType)}>({index}{parameterLink})" : - $"GetResultAsync<{ToFullString(method.ReturnType)}>({index}{parameterLink})"; + var methodsText = new List(); - if (!isVoid) - prefix = "return " + prefix; - - // if (method.ReturnType.OriginalDefinition.ToString() == "System.Threading.Tasks.Task") - // { - // var type = method.ReturnType.ToString(); - // type = type.Substring(type.IndexOf('<') + 1); - // type = type.Substring(0, type.Length - 1); - // sb.AppendLine( - // $"\t\tvar response = await serialisationModule.GetFinalCommandExecution<{type}>(defaultCallRequestCodegen.CallRequestId);"); - // sb.AppendLine($"\t\treturn ({type})response.Result;"); - // } - // else if (!isAsync && method.ReturnType.ToDisplayString() != "void") - // { - // var type = method.ReturnType.ToDisplayString(); - // sb.AppendLine( - // $"\t\tvar response = serialisationModule.GetFinalCommandExecution<{type}>(defaultCallRequestCodegen.CallRequestId).GetAwaiter().GetResult();"); - // sb.AppendLine($"\t\treturn ({type})response.Result;"); - // } - // else - // { - // sb.AppendLine( - // "\t\tserialisationModule.GetNextCommandExecution(defaultCallRequestCodegen.CallRequestId).Wait();"); - // } - // - // sb.AppendLine("\t}"); + foreach (var method in methodBody) + { + var index = methods.Count; + methods.Add((namespaceName + "." + originalName, method)); + var sb = new StringBuilder(); - sb.AppendLine("\t\t" + prefix + caller + postfix+ ";"); - - sb.AppendLine("\t}"); - methodsText.Add(sb.ToString()); - } + bool isAsync = method.ReturnType.Name == "Task"; + bool isVoid = method.ReturnType.Name == "Void" || method.ReturnType.ToString() == "Task"; + bool isParametrized = method.Parameters.Length == 1 && !isAsync || + method.Parameters.Length == 2 && isAsync; - var code = $@"// + + //Creating signature + sb.AppendLine("public" + (isAsync + ? " async " + : " ") + + $"{method.ReturnType.ToDisplayString()} {method.Name}({string.Join(", ", method.Parameters.Select(ToFullString))}){{"); + + + var prefix = isAsync ? "await " : ""; + var postfix = !isAsync ? (isVoid ? ".Wait()" : ".GetAwaiter().GetResult()") : ""; + var parameterLink = isParametrized ? ", " + method.Parameters.First().Name : string.Empty; + var caller = isVoid ? $"CallAsync({index}{parameterLink})" : + isAsync ? $"GetResultAsync<{ExtractTaskType(method.ReturnType)}>({index}{parameterLink})" : + $"GetResultAsync<{ToFullString(method.ReturnType)}>({index}{parameterLink})"; + + if (!isVoid) + prefix = "return " + prefix; + + // if (method.ReturnType.OriginalDefinition.ToString() == "System.Threading.Tasks.Task") + // { + // var type = method.ReturnType.ToString(); + // type = type.Substring(type.IndexOf('<') + 1); + // type = type.Substring(0, type.Length - 1); + // sb.AppendLine( + // $"\t\tvar response = await serialisationModule.GetFinalCommandExecution<{type}>(defaultCallRequestCodegen.CallRequestId);"); + // sb.AppendLine($"\t\treturn ({type})response.Result;"); + // } + // else if (!isAsync && method.ReturnType.ToDisplayString() != "void") + // { + // var type = method.ReturnType.ToDisplayString(); + // sb.AppendLine( + // $"\t\tvar response = serialisationModule.GetFinalCommandExecution<{type}>(defaultCallRequestCodegen.CallRequestId).GetAwaiter().GetResult();"); + // sb.AppendLine($"\t\treturn ({type})response.Result;"); + // } + // else + // { + // sb.AppendLine( + // "\t\tserialisationModule.GetNextCommandExecution(defaultCallRequestCodegen.CallRequestId).Wait();"); + // } + // + // sb.AppendLine("\t}"); + + sb.AppendLine("\t\t\t" + prefix + caller + postfix + ";"); + + sb.AppendLine("\t\t}"); + + methodsText.Add(sb.ToString()); + } + + var code = $@"// using mROA; using System; @@ -181,106 +181,168 @@ using mROA.Implementation; using System.Collections.Generic; using mROA.Abstract; -namespace {namespaceName}; - -partial class {className} : RemoteObjectBase, {originalName} +namespace {namespaceName} {{ - public {className}(int id, IRepresentationModule representationModule) : base(id, representationModule) + partial class {className} : RemoteObjectBase, {originalName} {{ - }} + public {className}(int id, IRepresentationModule representationModule) : base(id, representationModule) + {{ + }} - {string.Join("\r\n\t", methodsText)} + {string.Join("\r\n\t", methodsText)} + }} }} "; - // Add the source code to the compilation. - context.AddSource($"{className}.g.cs", SourceText.From(code, Encoding.UTF8)); - frontendContextRepo.Add( - $"{{ typeof({classSymbol.ToDisplayString()}), typeof({namespaceName}.{className}) }}"); - } + // Add the source code to the compilation. + context.AddSource($"{className}.g.cs", SourceText.From(code, Encoding.UTF8)); - if (methods.Count != 0) - { - var methodsStringed = methods.Select(i => - $"typeof({i.Item1}).GetMethod(\"{i.Item2.Name}\", [{string.Join(", ", i.Item2.Parameters.Select(p => $"typeof({p.Type.ToDisplayString()})"))}])") - .ToList(); + frontendContextRepo.Add( + $"{{ typeof({classSymbol.ToDisplayString()}), typeof({namespaceName}.{className}) }}"); + } - var coCodegenRepoCode = @$"// + if (methods.Count != 0) + { + var methodsStringed = methods.Select(i => + $"typeof({i.Item1}).GetMethod(\"{i.Item2.Name}\", new Type[] {{{string.Join(", ", i.Item2.Parameters.Select(p => $"typeof({p.Type.ToDisplayString()})"))}}})") + .ToList(); + + var coCodegenRepoCode = @$"// using System.Collections.Generic; using System.Reflection; using mROA.Abstract; +using System; -namespace mROA.Codegen; - -public class CoCodegenMethodRepository : IMethodRepository +namespace mROA.Codegen {{ - private readonly List _methods = [ - {string.Join(", // test comment\r\n\t\t", methodsStringed)} - ]; - public MethodInfo GetMethod(int id) + public class CoCodegenMethodRepository : IMethodRepository {{ - if (_methods.Count <= id) - return null; - - return _methods[id]; - }} + private readonly List _methods = new () {{ + {string.Join(",\r\n\t\t\t", methodsStringed)} + }}; - public int RegisterMethod(MethodInfo method) - {{ - _methods.Add(method); - return _methods.Count - 1; - }} + public MethodInfo GetMethod(int id) + {{ + if (_methods.Count <= id) + return null; + + return _methods[id]; + }} - public IEnumerable GetMethods() - {{ - return _methods; - }} + public int RegisterMethod(MethodInfo method) + {{ + _methods.Add(method); + return _methods.Count - 1; + }} - public void Inject(T dependency) - {{ + public IEnumerable GetMethods() + {{ + return _methods; + }} + + public void Inject(T dependency) + {{ + }} }} }} "; - context.AddSource($"CoCodegenMethodRepository.g.cs", SourceText.From(coCodegenRepoCode, Encoding.UTF8)); - } - - if (frontendContextRepo.Count != 0) - { - var fronendRepoCode = @$"// -using System.Collections.Frozen; + context.AddSource($"CoCodegenMethodRepository.g.cs", SourceText.From(coCodegenRepoCode, Encoding.UTF8)); + } + + if (frontendContextRepo.Count != 0) + { + var fronendRepoCode = @$"// using mROA.Implementation; using mROA.Abstract; +using System.Collections.Generic; +using System; +using System.Reflection; -namespace mROA.Codegen; - -public sealed class RemoteTypeBinder +namespace mROA.Codegen {{ - static RemoteTypeBinder(){{ - RemoteContextRepository.RemoteTypes = new Dictionary {{ - {string.Join(", \r\n\t\t", frontendContextRepo)}}}.ToFrozenDictionary(); + public sealed class RemoteTypeBinder + {{ + static RemoteTypeBinder(){{ + RemoteContextRepository.RemoteTypes = new Dictionary {{ + {string.Join(", \r\n\t\t\t", frontendContextRepo)}}}; + }} }} }} "; - context.AddSource("RemoteTypeBinder.g.cs", SourceText.From(fronendRepoCode, Encoding.UTF8)); + context.AddSource("RemoteTypeBinder.g.cs", SourceText.From(fronendRepoCode, Encoding.UTF8)); + } + } + + private static string ToFullString(IParameterSymbol parameter) + => /*parameter.Type.ContainingNamespace is null*/ + /*?*/ parameter.ToDisplayString(); + /*: $"{parameter.Type.ContainingNamespace.ToDisplayString()}.{parameter.Type.MetadataName} {parameter.Name}";*/ + + private static string ToFullString(ITypeSymbol type) => + // => type.ContainingNamespace is null || type.Name == "Void" + type.ToDisplayString(); + // : $"{type.ContainingNamespace.ToDisplayString()}.{type.MetadataName}"; + + private string ExtractTaskType(ITypeSymbol taskType) + { + var type = taskType.ToString(); + type = type.Substring(type.IndexOf('<') + 1); + return type.Substring(0, type.Length - 1); + } + + public void Initialize(GeneratorInitializationContext context) + { + } + + public void Execute(GeneratorExecutionContext context) + { + var trees = context.Compilation.SyntaxTrees; + + var interfaces = new List(); + foreach (var tree in trees) + { + var node = tree.GetRoot() as CompilationUnitSyntax; + + foreach (var member in node.Members) + { + if (member is InterfaceDeclarationSyntax ids) + { + interfaces.Add(ids); + } + else if (member is NamespaceDeclarationSyntax nds) + { + foreach (var inside in nds.Members) + + if (inside is InterfaceDeclarationSyntax ids2) + if (ContainsSOIAttribute(ids2.AttributeLists, context, ids2)) + interfaces.Add(ids2); + } + } + } + + GenerateCode(context, context.Compilation, interfaces.ToImmutableArray()); + } + + private bool ContainsSOIAttribute(SyntaxList attributes, GeneratorExecutionContext context, + InterfaceDeclarationSyntax interfaceDeclarationSyntax) + { + foreach (AttributeListSyntax attributeListSyntax in attributes) + foreach (AttributeSyntax attributeSyntax in attributeListSyntax.Attributes) + { + if (context.Compilation.GetSemanticModel(interfaceDeclarationSyntax.SyntaxTree) + .GetSymbolInfo(attributeSyntax).Symbol is not IMethodSymbol attributeSymbol) + continue; // if we can't get the symbol, ignore it + + string attributeName = attributeSymbol.ContainingType.ToDisplayString(); + + // Check the full name of the [Report] attribute. + if (attributeName == "mROA.Implementation.Attributes.SharedObjectInterfaceAttribute") + return true; + } + + return false; } } - - private static string ToFullString(IParameterSymbol parameter) - => /*parameter.Type.ContainingNamespace is null*/ - /*?*/ parameter.ToDisplayString(); - /*: $"{parameter.Type.ContainingNamespace.ToDisplayString()}.{parameter.Type.MetadataName} {parameter.Name}";*/ - - private static string ToFullString(ITypeSymbol type) => - // => type.ContainingNamespace is null || type.Name == "Void" - type.ToDisplayString(); - // : $"{type.ContainingNamespace.ToDisplayString()}.{type.MetadataName}"; - - private string ExtractTaskType(ITypeSymbol taskType) - { - var type = taskType.ToString(); - type = type.Substring(type.IndexOf('<') + 1); - return type.Substring(0, type.Length - 1); - } } \ No newline at end of file diff --git a/mROA.Test/NextGenTest.cs b/mROA.Test/NextGenTest.cs index 7293877..76a53c5 100644 --- a/mROA.Test/NextGenTest.cs +++ b/mROA.Test/NextGenTest.cs @@ -1,72 +1,76 @@ -using System.Net; +using System; +using System.Linq; +using System.Net; using System.Net.Sockets; using System.Text; +using System.Threading.Tasks; using mROA.Implementation; -namespace mROA.Test; - -public class NextGenTest +namespace mROA.Test { - private TcpListener _listener; - private NextGenerationInteractionModule _interactionModuleA; - private NextGenerationInteractionModule _interactionModuleB; - private Guid[] guids = [Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid()]; - - [SetUp] - public void Setup() + public class NextGenTest { - _listener = new TcpListener(IPAddress.Loopback, 4567); - _interactionModuleA = new NextGenerationInteractionModule(); - _interactionModuleA.Inject(new JsonSerializationToolkit()); - _interactionModuleB = new NextGenerationInteractionModule(); - _interactionModuleB.Inject(new JsonSerializationToolkit()); + private TcpListener _listener; + private NextGenerationInteractionModule _interactionModuleA; + private NextGenerationInteractionModule _interactionModuleB; + private Guid[] guids = new[] { Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid() }; - } - - [Test] - public void MultithreadedTest() - { - - Task.Run(() => + [SetUp] + public void Setup() { - _listener.Start(); - _interactionModuleB.BaseStream = _listener.AcceptTcpClient().GetStream(); + _listener = new TcpListener(IPAddress.Loopback, 4567); + _interactionModuleA = new NextGenerationInteractionModule(); + _interactionModuleA.Inject(new JsonSerializationToolkit()); + _interactionModuleB = new NextGenerationInteractionModule(); + _interactionModuleB.Inject(new JsonSerializationToolkit()); - foreach (var guid in guids) - { - _interactionModuleB.PostMessage(new NetworkMessage { Id = guid, Data = "Hello user"u8.ToArray() }); - } - }); - - var client = new TcpClient(); - client.Connect(IPAddress.Loopback, 4567); - _interactionModuleA.BaseStream = client.GetStream(); - - var tasks = guids.Select(ReadStream); - - Task.WaitAll(tasks.ToArray()); - Assert.Pass(); - - } - - private async Task ReadStream(Guid current) - { - var msg = await _interactionModuleA.GetNextMessageReceiving(); - Console.WriteLine( - $"{Environment.CurrentManagedThreadId} Received message: {Encoding.Default.GetString(new JsonSerializationToolkit().Serialize(msg))}"); - while (msg.Id != current) - { - msg = await _interactionModuleA.GetNextMessageReceiving(); - Console.WriteLine( - $"{Environment.CurrentManagedThreadId} Received message: {Encoding.Default.GetString(new JsonSerializationToolkit().Serialize(msg))}"); } - Console.WriteLine($"{Environment.CurrentManagedThreadId} Good message received"); - } + [Test] + public void MultithreadedTest() + { + + Task.Run(() => + { + _listener.Start(); + _interactionModuleB.BaseStream = _listener.AcceptTcpClient().GetStream(); - [TearDown] - public void TearDown() - { - _listener.Dispose(); + foreach (var guid in guids) + { + _interactionModuleB.PostMessage(new NetworkMessage { Id = guid, Data = "Hello user"u8.ToArray() }); + } + }); + + var client = new TcpClient(); + client.Connect(IPAddress.Loopback, 4567); + _interactionModuleA.BaseStream = client.GetStream(); + + var tasks = guids.Select(ReadStream); + + Task.WaitAll(tasks.ToArray()); + Assert.Pass(); + + } + + private async Task ReadStream(Guid current) + { + var msg = await _interactionModuleA.GetNextMessageReceiving(); + Console.WriteLine( + $"{Environment.CurrentManagedThreadId} Received message: {Encoding.Default.GetString(new JsonSerializationToolkit().Serialize(msg))}"); + while (msg.Id != current) + { + msg = await _interactionModuleA.GetNextMessageReceiving(); + Console.WriteLine( + $"{Environment.CurrentManagedThreadId} Received message: {Encoding.Default.GetString(new JsonSerializationToolkit().Serialize(msg))}"); + } + + Console.WriteLine($"{Environment.CurrentManagedThreadId} Good message received"); + } + + [TearDown] + public void TearDown() + { + _listener.Dispose(); + } } } \ No newline at end of file diff --git a/mROA.Test/mROA.Test.csproj b/mROA.Test/mROA.Test.csproj index 4262b31..4d1d9e4 100644 --- a/mROA.Test/mROA.Test.csproj +++ b/mROA.Test/mROA.Test.csproj @@ -1,9 +1,9 @@  - net9.0 + netstandard2.1 latest - enable + enable false diff --git a/mROA/Abstract/ICommandExecution.cs b/mROA/Abstract/ICommandExecution.cs index 4566f1d..210b976 100644 --- a/mROA/Abstract/ICommandExecution.cs +++ b/mROA/Abstract/ICommandExecution.cs @@ -1,8 +1,11 @@ -namespace mROA.Abstract; +using System; -public interface ICommandExecution +namespace mROA.Abstract { - Guid Id { get; init; } - int ClientId { get; set; } - int CommandId { get; } + public interface ICommandExecution + { + Guid Id { get; set; } + int ClientId { get; set; } + int CommandId { get; } + } } \ No newline at end of file diff --git a/mROA/Abstract/IConnectionHub.cs b/mROA/Abstract/IConnectionHub.cs index 1a595c8..43dc945 100644 --- a/mROA/Abstract/IConnectionHub.cs +++ b/mROA/Abstract/IConnectionHub.cs @@ -1,12 +1,13 @@ -namespace mROA.Abstract; - -public delegate void ConnectionHandler(IRepresentationModule representationModule); -public delegate void DisconnectionHandler(IRepresentationModule representationModule); - -public interface IConnectionHub : IInjectableModule +namespace mROA.Abstract { - void RegisterInteraction(INextGenerationInteractionModule interaction); - INextGenerationInteractionModule GetInteracion(int id); - event ConnectionHandler? OnConnected; - event DisconnectionHandler? OnDisconnected; + public delegate void ConnectionHandler(IRepresentationModule representationModule); + public delegate void DisconnectionHandler(IRepresentationModule representationModule); + + public interface IConnectionHub : IInjectableModule + { + void RegisterInteraction(INextGenerationInteractionModule interaction); + INextGenerationInteractionModule GetInteracion(int id); + event ConnectionHandler? OnConnected; + event DisconnectionHandler? OnDisconnected; + } } \ No newline at end of file diff --git a/mROA/Abstract/IContextRepository.cs b/mROA/Abstract/IContextRepository.cs index 754c39f..a54d5d6 100644 --- a/mROA/Abstract/IContextRepository.cs +++ b/mROA/Abstract/IContextRepository.cs @@ -1,11 +1,14 @@ -namespace mROA.Abstract; +using System; -public interface IContextRepository : IInjectableModule +namespace mROA.Abstract { - int ResisterObject(object o); - void ClearObject(int id); - object GetObject(int id); - T? GetObject(int id); - object GetSingleObject(Type type); - int GetObjectIndex(object o); + public interface IContextRepository : IInjectableModule + { + int ResisterObject(object o); + void ClearObject(int id); + object GetObject(int id); + T? GetObject(int id); + object GetSingleObject(Type type); + int GetObjectIndex(object o); + } } \ No newline at end of file diff --git a/mROA/Abstract/IContextRepositoryHub.cs b/mROA/Abstract/IContextRepositoryHub.cs index 8a34bf2..f950b8f 100644 --- a/mROA/Abstract/IContextRepositoryHub.cs +++ b/mROA/Abstract/IContextRepositoryHub.cs @@ -1,6 +1,7 @@ -namespace mROA.Abstract; - -public interface IContextRepositoryHub +namespace mROA.Abstract { - IContextRepository GetRepository(int clientId); + public interface IContextRepositoryHub + { + IContextRepository GetRepository(int clientId); + } } \ No newline at end of file diff --git a/mROA/Abstract/IExecuteModule.cs b/mROA/Abstract/IExecuteModule.cs index 7a9b0a1..2ebdd24 100644 --- a/mROA/Abstract/IExecuteModule.cs +++ b/mROA/Abstract/IExecuteModule.cs @@ -1,8 +1,9 @@ using mROA.Implementation; -namespace mROA.Abstract; - -public interface IExecuteModule : IInjectableModule +namespace mROA.Abstract { - ICommandExecution Execute(ICallRequest command, IContextRepository contextRepository); + public interface IExecuteModule : IInjectableModule + { + ICommandExecution Execute(ICallRequest command, IContextRepository contextRepository); + } } \ No newline at end of file diff --git a/mROA/Abstract/IFrontendBridge.cs b/mROA/Abstract/IFrontendBridge.cs index 103fec2..7d4eb3f 100644 --- a/mROA/Abstract/IFrontendBridge.cs +++ b/mROA/Abstract/IFrontendBridge.cs @@ -1,3 +1,7 @@ -namespace mROA.Abstract; - -public interface IFrontendBridge : IInjectableModule; \ No newline at end of file +namespace mROA.Abstract +{ + public interface IFrontendBridge : IInjectableModule + { + + } +} \ No newline at end of file diff --git a/mROA/Abstract/IGatewayModule.cs b/mROA/Abstract/IGatewayModule.cs index d51063a..46d96bd 100644 --- a/mROA/Abstract/IGatewayModule.cs +++ b/mROA/Abstract/IGatewayModule.cs @@ -1,6 +1,9 @@ -namespace mROA.Abstract; +using System; -public interface IGatewayModule : IDisposable, IInjectableModule -{ - void Run(); +namespace mROA.Abstract +{ + public interface IGatewayModule : IDisposable, IInjectableModule + { + void Run(); + } } \ No newline at end of file diff --git a/mROA/Abstract/IIdentityGenerator.cs b/mROA/Abstract/IIdentityGenerator.cs index bede9f3..6123cdd 100644 --- a/mROA/Abstract/IIdentityGenerator.cs +++ b/mROA/Abstract/IIdentityGenerator.cs @@ -1,6 +1,7 @@ -namespace mROA.Abstract; - -public interface IIdentityGenerator : IInjectableModule +namespace mROA.Abstract { - int GetNextIdentity(); + public interface IIdentityGenerator : IInjectableModule + { + int GetNextIdentity(); + } } \ No newline at end of file diff --git a/mROA/Abstract/IInjectableModule.cs b/mROA/Abstract/IInjectableModule.cs index d7da7cb..c516a6f 100644 --- a/mROA/Abstract/IInjectableModule.cs +++ b/mROA/Abstract/IInjectableModule.cs @@ -1,6 +1,7 @@ -namespace mROA.Abstract; - -public interface IInjectableModule +namespace mROA.Abstract { - void Inject(T dependency); + public interface IInjectableModule + { + void Inject(T dependency); + } } \ No newline at end of file diff --git a/mROA/Abstract/IInteractionModule.cs b/mROA/Abstract/IInteractionModule.cs index cb1072e..dc45dbf 100644 --- a/mROA/Abstract/IInteractionModule.cs +++ b/mROA/Abstract/IInteractionModule.cs @@ -1,14 +1,18 @@ +using System; +using System.IO; +using System.Threading.Tasks; using mROA.Implementation; -namespace mROA.Abstract; - -public interface INextGenerationInteractionModule : IInjectableModule +namespace mROA.Abstract { - int ConnectionId { get; } - public Stream? BaseStream { get; set; } - Task GetNextMessageReceiving(); - Task PostMessage(NetworkMessage message); - void HandleMessage(NetworkMessage message); - NetworkMessage[] UnhandledMessages { get; } - NetworkMessage? FirstByFilter(Predicate predicate); + public interface INextGenerationInteractionModule : IInjectableModule + { + int ConnectionId { get; } + public Stream? BaseStream { get; set; } + Task GetNextMessageReceiving(); + Task PostMessage(NetworkMessage message); + void HandleMessage(NetworkMessage message); + NetworkMessage[] UnhandledMessages { get; } + NetworkMessage? FirstByFilter(Predicate predicate); + } } \ No newline at end of file diff --git a/mROA/Abstract/IMethodRepository.cs b/mROA/Abstract/IMethodRepository.cs index d18405c..9e448f9 100644 --- a/mROA/Abstract/IMethodRepository.cs +++ b/mROA/Abstract/IMethodRepository.cs @@ -1,11 +1,13 @@ -using System.Reflection; +using System.Collections.Generic; +using System.Reflection; -namespace mROA.Abstract; - -public interface IMethodRepository : IInjectableModule +namespace mROA.Abstract { - MethodInfo GetMethod(int id); - int RegisterMethod(MethodInfo method); + public interface IMethodRepository : IInjectableModule + { + MethodInfo GetMethod(int id); + int RegisterMethod(MethodInfo method); - IEnumerable GetMethods(); + IEnumerable GetMethods(); + } } \ No newline at end of file diff --git a/mROA/Abstract/IOwnershipRepository.cs b/mROA/Abstract/IOwnershipRepository.cs index deccfe9..55ec3f3 100644 --- a/mROA/Abstract/IOwnershipRepository.cs +++ b/mROA/Abstract/IOwnershipRepository.cs @@ -1,7 +1,8 @@ -namespace mROA.Abstract; - -public interface IOwnershipRepository +namespace mROA.Abstract { - int GetOwnershipId(); - int GetHostOwnershipId(); + public interface IOwnershipRepository + { + int GetOwnershipId(); + int GetHostOwnershipId(); + } } \ No newline at end of file diff --git a/mROA/Abstract/IRepresentationModuleProducer.cs b/mROA/Abstract/IRepresentationModuleProducer.cs index 9162a5c..6406c78 100644 --- a/mROA/Abstract/IRepresentationModuleProducer.cs +++ b/mROA/Abstract/IRepresentationModuleProducer.cs @@ -1,6 +1,7 @@ -namespace mROA.Abstract; - -public interface IRepresentationModuleProducer : IInjectableModule +namespace mROA.Abstract { - IRepresentationModule Produce(int id); + public interface IRepresentationModuleProducer : IInjectableModule + { + IRepresentationModule Produce(int id); + } } \ No newline at end of file diff --git a/mROA/Abstract/IRequestExtractor.cs b/mROA/Abstract/IRequestExtractor.cs index eaf59de..d49194b 100644 --- a/mROA/Abstract/IRequestExtractor.cs +++ b/mROA/Abstract/IRequestExtractor.cs @@ -1,6 +1,9 @@ -namespace mROA.Abstract; +using System.Threading.Tasks; -public interface IRequestExtractor : IInjectableModule +namespace mROA.Abstract { - Task StartExtraction(); + public interface IRequestExtractor : IInjectableModule + { + Task StartExtraction(); + } } \ No newline at end of file diff --git a/mROA/Abstract/ISerialisationModule.cs b/mROA/Abstract/ISerialisationModule.cs index 14ea0ef..02292c2 100644 --- a/mROA/Abstract/ISerialisationModule.cs +++ b/mROA/Abstract/ISerialisationModule.cs @@ -1,31 +1,34 @@ +using System; +using System.Threading.Tasks; using mROA.Implementation; using mROA.Implementation.CommandExecution; -namespace mROA.Abstract; - -public interface ISerialisationModule : IInjectableModule +namespace mROA.Abstract { - void HandleIncomingRequest(int clientId, byte[] message); - void PostResponse(NetworkMessage message, int clientId); - void SendWelcomeMessage(int clientId); - public interface IFrontendSerialisationModule : IInjectableModule + public interface ISerialisationModule : IInjectableModule { - int ClientId { get; } - Task GetNextCommandExecution(Guid requestId) where T : ICommandExecution; - Task> GetFinalCommandExecution(Guid requestId); - void PostCallRequest(ICallRequest callRequest); + void HandleIncomingRequest(int clientId, byte[] message); + void PostResponse(NetworkMessage message, int clientId); + void SendWelcomeMessage(int clientId); + public interface IFrontendSerialisationModule : IInjectableModule + { + int ClientId { get; } + Task GetNextCommandExecution(Guid requestId) where T : ICommandExecution; + Task> GetFinalCommandExecution(Guid requestId); + void PostCallRequest(ICallRequest callRequest); + } } -} -public interface IRepresentationModule : IInjectableModule -{ - int Id { get; } - Task GetMessageAsync(Guid? requestId = null, MessageType? messageType = null); - T GetMessage(Guid? requestId = null, MessageType? messageType = null); - Task GetRawMessage(Guid? requestId = null, MessageType? messageType = null); + public interface IRepresentationModule : IInjectableModule + { + int Id { get; } + Task GetMessageAsync(Guid? requestId = null, MessageType? messageType = null); + T GetMessage(Guid? requestId = null, MessageType? messageType = null); + Task GetRawMessage(Guid? requestId = null, MessageType? messageType = null); - Task PostCallMessageAsync(Guid id, MessageType messageType, T payload) where T : notnull; - Task PostCallMessageAsync(Guid id, MessageType messageType, object payload, Type payloadType); - void PostCallMessage(Guid id, MessageType messageType, T payload) where T : notnull; - void PostCallMessage(Guid id, MessageType messageType, object payload, Type payloadType); + Task PostCallMessageAsync(Guid id, MessageType messageType, T payload) where T : notnull; + Task PostCallMessageAsync(Guid id, MessageType messageType, object payload, Type payloadType); + void PostCallMessage(Guid id, MessageType messageType, T payload) where T : notnull; + void PostCallMessage(Guid id, MessageType messageType, object payload, Type payloadType); + } } \ No newline at end of file diff --git a/mROA/Abstract/ISerializationToolkit.cs b/mROA/Abstract/ISerializationToolkit.cs index 769180a..fbb48d2 100644 --- a/mROA/Abstract/ISerializationToolkit.cs +++ b/mROA/Abstract/ISerializationToolkit.cs @@ -1,14 +1,17 @@ -namespace mROA.Abstract; +using System; -public interface ISerializationToolkit : IInjectableModule +namespace mROA.Abstract { - byte[] Serialize(T objectToSerialize); - byte[] Serialize(object objectToSerialize, Type type); - T? Deserialize(byte[] rawData); - object? Deserialize(byte[] rawData, Type type); - T? Deserialize(Span rawData); - object? Deserialize(Span rawData, Type type); - T Cast(object nonCasted); - object Cast(object nonCasted, Type type); + public interface ISerializationToolkit : IInjectableModule + { + byte[] Serialize(T objectToSerialize); + byte[] Serialize(object objectToSerialize, Type type); + T? Deserialize(byte[] rawData); + object? Deserialize(byte[] rawData, Type type); + T? Deserialize(Span rawData); + object? Deserialize(Span rawData, Type type); + T Cast(object nonCasted); + object Cast(object nonCasted, Type type); + } } \ No newline at end of file diff --git a/mROA/Implementation/Attributes/SharedObjectInterfaceAttribute.cs b/mROA/Implementation/Attributes/SharedObjectInterfaceAttribute.cs index 78bfa15..c187036 100644 --- a/mROA/Implementation/Attributes/SharedObjectInterfaceAttribute.cs +++ b/mROA/Implementation/Attributes/SharedObjectInterfaceAttribute.cs @@ -1,3 +1,6 @@ -namespace mROA.Implementation.Attributes; +using System; -public class SharedObjectInterfaceAttribute : Attribute; \ No newline at end of file +namespace mROA.Implementation.Attributes +{ + public class SharedObjectInterfaceAttribute : Attribute { } +} \ No newline at end of file diff --git a/mROA/Implementation/Attributes/SharedObjectSingletonAttribute.cs b/mROA/Implementation/Attributes/SharedObjectSingletonAttribute.cs index f0439f5..84002ac 100644 --- a/mROA/Implementation/Attributes/SharedObjectSingletonAttribute.cs +++ b/mROA/Implementation/Attributes/SharedObjectSingletonAttribute.cs @@ -1,3 +1,6 @@ -namespace mROA.Implementation.Attributes; +using System; -public class SharedObjectSingletonAttribute : Attribute; \ No newline at end of file +namespace mROA.Implementation.Attributes +{ + public class SharedObjectSingletonAttribute : Attribute { } +} \ No newline at end of file diff --git a/mROA/Implementation/Backend/BackendIdentityGenerator.cs b/mROA/Implementation/Backend/BackendIdentityGenerator.cs index 82dd4e2..ae49490 100644 --- a/mROA/Implementation/Backend/BackendIdentityGenerator.cs +++ b/mROA/Implementation/Backend/BackendIdentityGenerator.cs @@ -1,17 +1,18 @@ using mROA.Abstract; -namespace mROA.Implementation.Backend; - -public class BackendIdentityGenerator : IIdentityGenerator +namespace mROA.Implementation.Backend { - private int _currentId; - - public int GetNextIdentity() - { - return ++_currentId; - } - - public void Inject(T dependency) + public class BackendIdentityGenerator : IIdentityGenerator { + private int _currentId; + + public int GetNextIdentity() + { + return ++_currentId; + } + + public void Inject(T dependency) + { + } } } \ No newline at end of file diff --git a/mROA/Implementation/Backend/BasicConfigurationExtensions.cs b/mROA/Implementation/Backend/BasicConfigurationExtensions.cs index 1fbdbf3..16b1851 100644 --- a/mROA/Implementation/Backend/BasicConfigurationExtensions.cs +++ b/mROA/Implementation/Backend/BasicConfigurationExtensions.cs @@ -1,37 +1,39 @@ +using System; using System.Net; using System.Reflection; using mROA.Abstract; using mROA.Implementation.Bootstrap; -namespace mROA.Implementation.Backend; - -public static class BasicConfigurationExtensions +namespace mROA.Implementation.Backend { - public static void UseJsonSerialisation(this FullMixBuilder builder) + public static class BasicConfigurationExtensions { - builder.Modules.Add(new JsonSerializationToolkit()); - } + public static void UseJsonSerialisation(this FullMixBuilder builder) + { + builder.Modules.Add(new JsonSerializationToolkit()); + } - public static void UseNetworkGateway(this FullMixBuilder builder, IPEndPoint endPoint, Type interactionModuleType, params IInjectableModule[] injectableModules) - { - builder.Modules.Add(new NetworkGatewayModule(endPoint, interactionModuleType, injectableModules)); - } + public static void UseNetworkGateway(this FullMixBuilder builder, IPEndPoint endPoint, Type interactionModuleType, params IInjectableModule[] injectableModules) + { + builder.Modules.Add(new NetworkGatewayModule(endPoint, interactionModuleType, injectableModules)); + } - public static void UseBasicExecution(this FullMixBuilder builder) - { - builder.Modules.Add(new BasicExecutionModule()); - } + public static void UseBasicExecution(this FullMixBuilder builder) + { + builder.Modules.Add(new BasicExecutionModule()); + } - public static void UseCollectableContextRepository(this FullMixBuilder builder, params Assembly[] assemblies) - { - var repo = new ContextRepository(); - repo.FillSingletons(assemblies); - TransmissionConfig.RealContextRepository = repo; - builder.Modules.Add(repo); - } + public static void UseCollectableContextRepository(this FullMixBuilder builder, params Assembly[] assemblies) + { + var repo = new ContextRepository(); + repo.FillSingletons(assemblies); + TransmissionConfig.RealContextRepository = repo; + builder.Modules.Add(repo); + } - public static void SetupMethodsRepository(this FullMixBuilder builder, IMethodRepository methodRepository) - { - builder.Modules.Add(methodRepository); + public static void SetupMethodsRepository(this FullMixBuilder builder, IMethodRepository methodRepository) + { + builder.Modules.Add(methodRepository); + } } } \ No newline at end of file diff --git a/mROA/Implementation/Backend/BasicExecutionModule.cs b/mROA/Implementation/Backend/BasicExecutionModule.cs index e3d9903..8f5ac39 100644 --- a/mROA/Implementation/Backend/BasicExecutionModule.cs +++ b/mROA/Implementation/Backend/BasicExecutionModule.cs @@ -1,121 +1,128 @@ -using System.Reflection; +using System; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; using mROA.Abstract; using mROA.Implementation.CommandExecution; -namespace mROA.Implementation.Backend; - -public class BasicExecutionModule : IExecuteModule +namespace mROA.Implementation.Backend { - private IMethodRepository? _methodRepo; - - public void Inject(T dependency) + public class BasicExecutionModule : IExecuteModule { - if (dependency is IMethodRepository methodRepo) _methodRepo = methodRepo; - } + private IMethodRepository? _methodRepo; - public ICommandExecution Execute(ICallRequest command, IContextRepository contextRepository) - { - if (_methodRepo is null) - throw new NullReferenceException("Method repository was not defined"); + public void Inject(T dependency) + { + if (dependency is IMethodRepository methodRepo) _methodRepo = methodRepo; + } + + public ICommandExecution Execute(ICallRequest command, IContextRepository contextRepository) + { + if (_methodRepo is null) + throw new NullReferenceException("Method repository was not defined"); - if (contextRepository is null) - throw new NullReferenceException("Context repository was not defined"); + if (contextRepository is null) + throw new NullReferenceException("Context repository was not defined"); - var currentCommand = _methodRepo.GetMethod(command.CommandId); - if (currentCommand == null) - throw new Exception($"Command {command.CommandId} not found"); + var currentCommand = _methodRepo.GetMethod(command.CommandId); + if (currentCommand == null) + throw new Exception($"Command {command.CommandId} not found"); - var context = command.ObjectId != -1 - ? contextRepository.GetObject(command.ObjectId) - : contextRepository.GetSingleObject(currentCommand.DeclaringType!); - var parameter = command.Parameter; + var context = command.ObjectId != -1 + ? contextRepository.GetObject(command.ObjectId) + : contextRepository.GetSingleObject(currentCommand.DeclaringType!); + var parameter = command.Parameter; - if (currentCommand.ReturnType.BaseType == typeof(Task) && - currentCommand.ReturnType.GenericTypeArguments.Length == 1) - return TypedExecuteAsync(currentCommand, context, parameter, command); + if (currentCommand.ReturnType.BaseType == typeof(Task) && + currentCommand.ReturnType.GenericTypeArguments.Length == 1) + return TypedExecuteAsync(currentCommand, context, parameter, command); - if (currentCommand.ReturnType == typeof(Task)) - return ExecuteAsync(currentCommand, context, parameter, command); + if (currentCommand.ReturnType == typeof(Task)) + return ExecuteAsync(currentCommand, context, parameter, command); - return Execute(currentCommand, context, parameter, command); - } - - private static ICommandExecution Execute(MethodInfo currentCommand, object context, object? parameter, - ICallRequest command) - { - try - { - var finalResult = currentCommand.Invoke(context, parameter is null ? [] : [parameter]); - return new TypedFinalCommandExecution - { - CommandId = command.CommandId, Result = finalResult, - Id = command.Id, - Type = currentCommand.ReturnType - }; + return Execute(currentCommand, context, parameter, command); } - catch (Exception e) + + private static ICommandExecution Execute(MethodInfo currentCommand, object context, object? parameter, + ICallRequest command) { - return new ExceptionCommandExecution + try { - Id = command.Id, CommandId = command.CommandId, - Exception = e.ToString() - }; - } - } - - private static ICommandExecution ExecuteAsync(MethodInfo currentCommand, object context, object? parameter, - ICallRequest command) - { - var tokenSource = new CancellationTokenSource(); - var token = tokenSource.Token; - try - { - var result = (Task)currentCommand.Invoke(context, parameter is null ? [token] : [parameter, token])!; - - - result.Wait(token); - - - return new FinalCommandExecution { CommandId = command.CommandId, Id = command.Id }; - } - catch (Exception e) - { - return new ExceptionCommandExecution + var finalResult = currentCommand.Invoke(context, parameter is null ? new object[0] : new[] + { parameter }); + return new TypedFinalCommandExecution + { + CommandId = command.CommandId, Result = finalResult, + Id = command.Id, + Type = currentCommand.ReturnType + }; + } + catch (Exception e) { - Id = command.Id, CommandId = command.CommandId, - Exception = e.ToString() - }; + return new ExceptionCommandExecution + { + Id = command.Id, CommandId = command.CommandId, + Exception = e.ToString() + }; + } } - } - private static ICommandExecution TypedExecuteAsync(MethodInfo currentCommand, object context, object? parameter, - ICallRequest command) - { - var tokenSource = new CancellationTokenSource(); - var token = tokenSource.Token; - try + private static ICommandExecution ExecuteAsync(MethodInfo currentCommand, object context, object? parameter, + ICallRequest command) { - var result = - (Task)currentCommand.Invoke(context, parameter is null ? [token] : [parameter, token])!; - - result.Wait(token); - - var finalResult = result.GetType().GetProperty("Result")?.GetValue(result); - return new TypedFinalCommandExecution + var tokenSource = new CancellationTokenSource(); + var token = tokenSource.Token; + try { - Id = command.Id, - Result = finalResult, - CommandId = command.CommandId, - Type = finalResult?.GetType() - }; + var result = (Task)currentCommand.Invoke(context, parameter is null ? new object[] { token } : new[] + { parameter, token })!; + + + result.Wait(token); + + + return new FinalCommandExecution { CommandId = command.CommandId, Id = command.Id }; + } + catch (Exception e) + { + return new ExceptionCommandExecution + { + Id = command.Id, CommandId = command.CommandId, + Exception = e.ToString() + }; + } } - catch (Exception e) + + private static ICommandExecution TypedExecuteAsync(MethodInfo currentCommand, object context, object? parameter, + ICallRequest command) { - return new ExceptionCommandExecution + var tokenSource = new CancellationTokenSource(); + var token = tokenSource.Token; + try { - Id = command.Id, CommandId = command.CommandId, - Exception = e.ToString() - }; + var result = + (Task)currentCommand.Invoke(context, parameter is null ? new object[] { token } : new[] + { parameter, token })!; + + result.Wait(token); + + var finalResult = result.GetType().GetProperty("Result")?.GetValue(result); + return new TypedFinalCommandExecution + { + Id = command.Id, + Result = finalResult, + CommandId = command.CommandId, + Type = finalResult?.GetType() + }; + } + catch (Exception e) + { + return new ExceptionCommandExecution + { + Id = command.Id, CommandId = command.CommandId, + Exception = e.ToString() + }; + } } } } \ No newline at end of file diff --git a/mROA/Implementation/Backend/ConnectionHub.cs b/mROA/Implementation/Backend/ConnectionHub.cs index e2c0c18..61fa56c 100644 --- a/mROA/Implementation/Backend/ConnectionHub.cs +++ b/mROA/Implementation/Backend/ConnectionHub.cs @@ -1,35 +1,38 @@ -using mROA.Abstract; +using System; +using System.Collections.Generic; +using mROA.Abstract; -namespace mROA.Implementation.Backend; - -public class ConnectionHub : IConnectionHub +namespace mROA.Implementation.Backend { - private readonly Dictionary _connections = new(); - private ISerializationToolkit? _serializationToolkit; + public class ConnectionHub : IConnectionHub + { + private readonly Dictionary _connections = new(); + private ISerializationToolkit? _serializationToolkit; - public void RegisterInteraction(INextGenerationInteractionModule interaction) - { - if (_serializationToolkit is null) - throw new NullReferenceException("Serialization toolkit is null"); + public void RegisterInteraction(INextGenerationInteractionModule interaction) + { + if (_serializationToolkit is null) + throw new NullReferenceException("Serialization toolkit is null"); - _connections.Add(interaction.ConnectionId, interaction); - var module = new RepresentationModule(); - module.Inject(_serializationToolkit); - module.Inject(interaction); - OnConnected?.Invoke(module); - } + _connections.Add(interaction.ConnectionId, interaction); + var module = new RepresentationModule(); + module.Inject(_serializationToolkit); + module.Inject(interaction); + OnConnected?.Invoke(module); + } - public INextGenerationInteractionModule GetInteracion(int id) - { - return _connections!.GetValueOrDefault(id, null) ?? throw new Exception("No connection found"); - } + public INextGenerationInteractionModule GetInteracion(int id) + { + return _connections!.GetValueOrDefault(id, null) ?? throw new Exception("No connection found"); + } - public event ConnectionHandler? OnConnected; - public event DisconnectionHandler? OnDisconnected; - public void Inject(T dependency) - { - if (dependency is ISerializationToolkit serializationToolkit) - _serializationToolkit = serializationToolkit; + public event ConnectionHandler? OnConnected; + public event DisconnectionHandler? OnDisconnected; + public void Inject(T dependency) + { + if (dependency is ISerializationToolkit serializationToolkit) + _serializationToolkit = serializationToolkit; + } } } \ No newline at end of file diff --git a/mROA/Implementation/Backend/ContextRepository.cs b/mROA/Implementation/Backend/ContextRepository.cs index 8ee451d..2831a38 100644 --- a/mROA/Implementation/Backend/ContextRepository.cs +++ b/mROA/Implementation/Backend/ContextRepository.cs @@ -1,88 +1,92 @@ -using System.Collections.Frozen; +using System; +using System.Collections.Generic; +using System.Linq; using System.Reflection; +using System.Threading.Tasks; using mROA.Abstract; using mROA.Implementation.Attributes; -namespace mROA.Implementation.Backend; - -public class ContextRepository : IContextRepository +namespace mROA.Implementation.Backend { - private FrozenDictionary? _singletons; - private object?[] _storage = new object[StartupSize]; - - private Task _lastIndexFinder = Task.FromResult(0); - - private const int StartupSize = 1024; - private const int GrowSize = 128; - - - public void FillSingletons(params Assembly[] assembly) + public class ContextRepository : IContextRepository { - var types = assembly.SelectMany(x => x.GetTypes()).Where(type => - type is { IsClass: true, IsAbstract: false, IsGenericType: false } && - type.GetCustomAttributes(typeof(SharedObjectSingletonAttribute), true).Length > 0); - _singletons = - types.ToFrozenDictionary( - t => t.GetInterfaces().FirstOrDefault(i => - i.GetCustomAttributes(typeof(SharedObjectInterfaceAttribute), true).Length > 0)!.GetHashCode(), - Activator.CreateInstance); - } + private Dictionary? _singletons; + private object?[] _storage = new object[StartupSize]; - public int ResisterObject(object o) - { - if (!_lastIndexFinder.IsCompleted) - _lastIndexFinder.Wait(); + private Task _lastIndexFinder = Task.FromResult(0); - _storage[_lastIndexFinder.Result] = o; + private const int StartupSize = 1024; + private const int GrowSize = 128; - var last = _lastIndexFinder.Result; - _lastIndexFinder = Task.Run(FindLastIndex); - return last; - } - - public void ClearObject(int id) - { - _storage[id] = null; - _lastIndexFinder = Task.FromResult(id); - } - - public object GetObject(int id) - { - return (id == -1 || _storage.Length <= id ? null : _storage[id]) ?? throw new NullReferenceException(); - } - - public T GetObject(int id) - { - return id == -1 || _storage.Length <= id ? throw new NullReferenceException("Cannot find that object. It is null"): (T)_storage[id]!; - } - - public object GetSingleObject(Type type) - { - return _singletons!.GetValueOrDefault(type.GetHashCode()) ?? throw new ArgumentException("Unregistered singleton type"); - } - - public int GetObjectIndex(object o) - { - var index = Array.IndexOf(_storage, o); - return index == -1 ? ResisterObject(o) : index; - } - - private int FindLastIndex() - { - for (var i = 0; i < _storage.Length; i++) + public void FillSingletons(params Assembly[] assembly) { - if (_storage[i] is null) - return i; + var types = assembly.SelectMany(x => x.GetTypes()).Where(type => + type is { IsClass: true, IsAbstract: false, IsGenericType: false } && + type.GetCustomAttributes(typeof(SharedObjectSingletonAttribute), true).Length > 0); + _singletons = + types.ToDictionary( + t => t.GetInterfaces().FirstOrDefault(i => + i.GetCustomAttributes(typeof(SharedObjectInterfaceAttribute), true).Length > 0)!.GetHashCode(), + Activator.CreateInstance); } - var nextStorage = new object[_storage.Length + GrowSize]; - Array.Copy(_storage, nextStorage, _storage.Length); - _storage = nextStorage; - return _storage.Length; - } - public void Inject(T dependency) - { - } + public int ResisterObject(object o) + { + if (!_lastIndexFinder.IsCompleted) + _lastIndexFinder.Wait(); + _storage[_lastIndexFinder.Result] = o; + + var last = _lastIndexFinder.Result; + _lastIndexFinder = Task.Run(FindLastIndex); + + return last; + } + + public void ClearObject(int id) + { + _storage[id] = null; + _lastIndexFinder = Task.FromResult(id); + } + + public object GetObject(int id) + { + return (id == -1 || _storage.Length <= id ? null : _storage[id]) ?? throw new NullReferenceException(); + } + + public T GetObject(int id) + { + return id == -1 || _storage.Length <= id ? throw new NullReferenceException("Cannot find that object. It is null"): (T)_storage[id]!; + } + + public object GetSingleObject(Type type) + { + return _singletons!.GetValueOrDefault(type.GetHashCode()) ?? throw new ArgumentException("Unregistered singleton type"); + } + + public int GetObjectIndex(object o) + { + var index = Array.IndexOf(_storage, o); + return index == -1 ? ResisterObject(o) : index; + } + + private int FindLastIndex() + { + for (var i = 0; i < _storage.Length; i++) + { + if (_storage[i] is null) + return i; + } + + var nextStorage = new object[_storage.Length + GrowSize]; + Array.Copy(_storage, nextStorage, _storage.Length); + _storage = nextStorage; + return _storage.Length; + } + public void Inject(T dependency) + { + } + + } } \ No newline at end of file diff --git a/mROA/Implementation/Backend/HubRequestExtractor.cs b/mROA/Implementation/Backend/HubRequestExtractor.cs index ae29e29..3bad121 100644 --- a/mROA/Implementation/Backend/HubRequestExtractor.cs +++ b/mROA/Implementation/Backend/HubRequestExtractor.cs @@ -1,50 +1,58 @@ +using System; using mROA.Abstract; -namespace mROA.Implementation.Backend; - -public class HubRequestExtractor(Type extractoType) : IInjectableModule +namespace mROA.Implementation.Backend { - private IConnectionHub? _hub; - - private IContextRepository? _contextRepository; - private IMethodRepository? _methodRepository; - private ISerializationToolkit? _serializationToolkit; - private IExecuteModule? _executeModule; - - public void Inject(T dependency) + public class HubRequestExtractor : IInjectableModule { - switch (dependency) + private IConnectionHub? _hub; + + private IContextRepository? _contextRepository; + private IMethodRepository? _methodRepository; + private ISerializationToolkit? _serializationToolkit; + private IExecuteModule? _executeModule; + private readonly Type _extractorType; + + public HubRequestExtractor(Type extractorType) { - case IConnectionHub connectionHub: - _hub = connectionHub; - _hub.OnConnected += HubOnOnConnected; - break; - case IContextRepository contextRepository: - _contextRepository = contextRepository; - break; - case IMethodRepository methodRepository: - _methodRepository = methodRepository; - break; - case ISerializationToolkit serializationToolkit: - _serializationToolkit = serializationToolkit; - break; - case IExecuteModule executeModule: - _executeModule = executeModule; - break; + _extractorType = extractorType; + } + + public void Inject(T dependency) + { + switch (dependency) + { + case IConnectionHub connectionHub: + _hub = connectionHub; + _hub.OnConnected += HubOnOnConnected; + break; + case IContextRepository contextRepository: + _contextRepository = contextRepository; + break; + case IMethodRepository methodRepository: + _methodRepository = methodRepository; + break; + case ISerializationToolkit serializationToolkit: + _serializationToolkit = serializationToolkit; + break; + case IExecuteModule executeModule: + _executeModule = executeModule; + break; + } + } + + private void HubOnOnConnected(IRepresentationModule interaction) + { + var extractor = (IRequestExtractor)Activator.CreateInstance(_extractorType)!; + extractor.Inject(interaction); + if (_contextRepository is IContextRepositoryHub contextHub) + extractor.Inject(contextHub.GetRepository(interaction.Id)); + else + extractor.Inject(interaction); + extractor.Inject(_methodRepository); + extractor.Inject(_serializationToolkit); + extractor.Inject(_executeModule); + _ = extractor.StartExtraction(); } } - - private void HubOnOnConnected(IRepresentationModule interaction) - { - var extractor = (IRequestExtractor)Activator.CreateInstance(extractoType)!; - extractor.Inject(interaction); - if (_contextRepository is IContextRepositoryHub contextHub) - extractor.Inject(contextHub.GetRepository(interaction.Id)); - else - extractor.Inject(interaction); - extractor.Inject(_methodRepository); - extractor.Inject(_serializationToolkit); - extractor.Inject(_executeModule); - _ = extractor.StartExtraction(); - } } \ No newline at end of file diff --git a/mROA/Implementation/Backend/MultiClientContextRepository.cs b/mROA/Implementation/Backend/MultiClientContextRepository.cs index 5bcce54..5aa906a 100644 --- a/mROA/Implementation/Backend/MultiClientContextRepository.cs +++ b/mROA/Implementation/Backend/MultiClientContextRepository.cs @@ -1,56 +1,65 @@ +using System; +using System.Collections.Generic; using mROA.Abstract; -namespace mROA.Implementation.Backend; - -public class MultiClientContextRepository(Func produceRepository) : IContextRepository, IContextRepositoryHub +namespace mROA.Implementation.Backend { - private Dictionary _repositories = new(); - - private IContextRepository GetRepositoryByClientId(int clientId) + public class MultiClientContextRepository : IContextRepository, IContextRepositoryHub { - if (_repositories.TryGetValue(clientId, out var repository)) - return repository; + private Dictionary _repositories = new(); + private readonly Func _produceRepository; + + public MultiClientContextRepository(Func produceRepository) + { + _produceRepository = produceRepository; + } + + private IContextRepository GetRepositoryByClientId(int clientId) + { + if (_repositories.TryGetValue(clientId, out var repository)) + return repository; - var created = produceRepository(clientId); - _repositories.Add(clientId, created); - return created; - } - public void Inject(T dependency) - { - } + var created = _produceRepository(clientId); + _repositories.Add(clientId, created); + return created; + } + public void Inject(T dependency) + { + } - public int ResisterObject(object o) - { - return GetRepositoryByClientId(TransmissionConfig.OwnershipRepository.GetOwnershipId()).ResisterObject(o); - } + public int ResisterObject(object o) + { + return GetRepositoryByClientId(TransmissionConfig.OwnershipRepository.GetOwnershipId()).ResisterObject(o); + } - public void ClearObject(int id) - { - GetRepositoryByClientId(TransmissionConfig.OwnershipRepository.GetOwnershipId()).ClearObject(id); - } + public void ClearObject(int id) + { + GetRepositoryByClientId(TransmissionConfig.OwnershipRepository.GetOwnershipId()).ClearObject(id); + } - public object GetObject(int id) - { - return GetRepositoryByClientId(TransmissionConfig.OwnershipRepository.GetOwnershipId()).GetObject(id); - } + public object GetObject(int id) + { + return GetRepositoryByClientId(TransmissionConfig.OwnershipRepository.GetOwnershipId()).GetObject(id); + } - public T? GetObject(int id) - { - return GetRepositoryByClientId(TransmissionConfig.OwnershipRepository.GetOwnershipId()).GetObject(id); - } + public T? GetObject(int id) + { + return GetRepositoryByClientId(TransmissionConfig.OwnershipRepository.GetOwnershipId()).GetObject(id); + } - public object GetSingleObject(Type type) - { - return GetRepositoryByClientId(TransmissionConfig.OwnershipRepository.GetOwnershipId()).GetSingleObject(type); - } + public object GetSingleObject(Type type) + { + return GetRepositoryByClientId(TransmissionConfig.OwnershipRepository.GetOwnershipId()).GetSingleObject(type); + } - public int GetObjectIndex(object o) - { - return GetRepositoryByClientId(TransmissionConfig.OwnershipRepository.GetOwnershipId()).GetObjectIndex(o); - } + public int GetObjectIndex(object o) + { + return GetRepositoryByClientId(TransmissionConfig.OwnershipRepository.GetOwnershipId()).GetObjectIndex(o); + } - public IContextRepository GetRepository(int clientId) - { - return GetRepositoryByClientId(clientId); + public IContextRepository GetRepository(int clientId) + { + return GetRepositoryByClientId(clientId); + } } } \ No newline at end of file diff --git a/mROA/Implementation/Backend/MultiClientOwnershipRepository.cs b/mROA/Implementation/Backend/MultiClientOwnershipRepository.cs index 93f8aa8..56cd389 100644 --- a/mROA/Implementation/Backend/MultiClientOwnershipRepository.cs +++ b/mROA/Implementation/Backend/MultiClientOwnershipRepository.cs @@ -1,28 +1,31 @@ -using mROA.Abstract; +using System; +using System.Collections.Generic; +using mROA.Abstract; -namespace mROA.Implementation.Backend; - -public class MultiClientOwnershipRepository : IOwnershipRepository +namespace mROA.Implementation.Backend { - private Dictionary _ownerships = new(); - - public int GetOwnershipId() + public class MultiClientOwnershipRepository : IOwnershipRepository { - return _ownerships.GetValueOrDefault(Environment.CurrentManagedThreadId, 0); - } + private Dictionary _ownerships = new(); - public int GetHostOwnershipId() - { - return 0; - } + public int GetOwnershipId() + { + return _ownerships.GetValueOrDefault(Environment.CurrentManagedThreadId, 0); + } - public void RegisterOwnership(int ownershipId) - { - _ownerships.TryAdd(Environment.CurrentManagedThreadId, ownershipId); - } + public int GetHostOwnershipId() + { + return 0; + } - public void FreeOwnership() - { - _ownerships.Remove(Environment.CurrentManagedThreadId); + public void RegisterOwnership(int ownershipId) + { + _ownerships.TryAdd(Environment.CurrentManagedThreadId, ownershipId); + } + + public void FreeOwnership() + { + _ownerships.Remove(Environment.CurrentManagedThreadId); + } } } \ No newline at end of file diff --git a/mROA/Implementation/Backend/NetworkGatewayModule.cs b/mROA/Implementation/Backend/NetworkGatewayModule.cs index c62cfc1..aeba65c 100644 --- a/mROA/Implementation/Backend/NetworkGatewayModule.cs +++ b/mROA/Implementation/Backend/NetworkGatewayModule.cs @@ -1,89 +1,91 @@ -using System.Net; +using System; +using System.Net; using System.Net.Sockets; +using System.Threading.Tasks; using mROA.Abstract; -namespace mROA.Implementation.Backend; - -public class NetworkGatewayModule : IGatewayModule +namespace mROA.Implementation.Backend { - private readonly Type? _interactionModuleType; - private readonly IInjectableModule[]? _injectableModules; - private readonly TcpListener _tcpListener; - private IConnectionHub? _hub; - private ISerializationToolkit? _serialization; - - public NetworkGatewayModule(IPEndPoint endpoint, Type interactionModuleType, IInjectableModule[] injectableModules) + public class NetworkGatewayModule : IGatewayModule { - _tcpListener = new(endpoint); - _interactionModuleType = interactionModuleType; - _injectableModules = injectableModules; - } + private readonly Type? _interactionModuleType; + private readonly IInjectableModule[]? _injectableModules; + private readonly TcpListener _tcpListener; + private IConnectionHub? _hub; + private ISerializationToolkit? _serialization; - public void Run() - { - _tcpListener.Start(); - Console.WriteLine($"Listening on {_tcpListener.LocalEndpoint}"); - Console.WriteLine("Enter Backspace to stop"); - - Task.Run(HandleIncomingConnections); - - while (true) + public NetworkGatewayModule(IPEndPoint endpoint, Type interactionModuleType, IInjectableModule[] injectableModules) { - var key = Console.ReadKey(); - if (key.Key == ConsoleKey.Backspace) - break; + _tcpListener = new(endpoint); + _interactionModuleType = interactionModuleType; + _injectableModules = injectableModules; } - Console.WriteLine("Stopping"); - } - - public void Dispose() - { - _tcpListener.Stop(); - _tcpListener.Dispose(); - } - - private void HandleIncomingConnections() - { - if (_hub is null) - throw new NullReferenceException("Hub module is null"); - if (_tcpListener == null) - throw new NullReferenceException("TcpListener is null"); - if (_injectableModules is null) - throw new NullReferenceException("InjectableModules is null"); - if (_interactionModuleType is null) - throw new NullReferenceException("InteractionModuleType is null"); - if (_serialization is null) - throw new NullReferenceException("Serialization is null"); - - while (true) + public void Run() { - var client = _tcpListener.AcceptTcpClient(); - Console.WriteLine($"Client connected from {client.Client.RemoteEndPoint}"); - var interaction = Activator.CreateInstance(_interactionModuleType) as INextGenerationInteractionModule; + _tcpListener.Start(); + Console.WriteLine($"Listening on {_tcpListener.LocalEndpoint}"); + Console.WriteLine("Enter Backspace to stop"); - foreach (var injectableModule in _injectableModules) - interaction!.Inject(injectableModule); + Task.Run(HandleIncomingConnections); - interaction!.Inject(_serialization); - - interaction.BaseStream = client.GetStream(); - - interaction.PostMessage(new NetworkMessage + while (true) { - Id = Guid.NewGuid(), SchemaId = MessageType.IdAssigning, - Data = _serialization.Serialize(new IdAssingnment { Id = interaction.ConnectionId }) - }); - _hub.RegisterInteraction(interaction); - Console.WriteLine("Client registered"); - } - } + var key = Console.ReadKey(); + if (key.Key == ConsoleKey.Backspace) + break; + } - public void Inject(T dependency) - { - if (dependency is IConnectionHub interactionModule) - _hub = interactionModule; - if (dependency is ISerializationToolkit serializationToolkit) - _serialization = serializationToolkit; + Console.WriteLine("Stopping"); + } + + public void Dispose() + { + _tcpListener.Stop(); + } + + private void HandleIncomingConnections() + { + if (_hub is null) + throw new NullReferenceException("Hub module is null"); + if (_tcpListener == null) + throw new NullReferenceException("TcpListener is null"); + if (_injectableModules is null) + throw new NullReferenceException("InjectableModules is null"); + if (_interactionModuleType is null) + throw new NullReferenceException("InteractionModuleType is null"); + if (_serialization is null) + throw new NullReferenceException("Serialization is null"); + + while (true) + { + var client = _tcpListener.AcceptTcpClient(); + Console.WriteLine($"Client connected from {client.Client.RemoteEndPoint}"); + var interaction = Activator.CreateInstance(_interactionModuleType) as INextGenerationInteractionModule; + + foreach (var injectableModule in _injectableModules) + interaction!.Inject(injectableModule); + + interaction!.Inject(_serialization); + + interaction.BaseStream = client.GetStream(); + + interaction.PostMessage(new NetworkMessage + { + Id = Guid.NewGuid(), SchemaId = MessageType.IdAssigning, + Data = _serialization.Serialize(new IdAssingnment { Id = interaction.ConnectionId }) + }); + _hub.RegisterInteraction(interaction); + Console.WriteLine("Client registered"); + } + } + + public void Inject(T dependency) + { + if (dependency is IConnectionHub interactionModule) + _hub = interactionModule; + if (dependency is ISerializationToolkit serializationToolkit) + _serialization = serializationToolkit; + } } } \ No newline at end of file diff --git a/mROA/Implementation/Bootstrap/FullMixBuilder.cs b/mROA/Implementation/Bootstrap/FullMixBuilder.cs index 848480d..3b7a9ae 100644 --- a/mROA/Implementation/Bootstrap/FullMixBuilder.cs +++ b/mROA/Implementation/Bootstrap/FullMixBuilder.cs @@ -1,20 +1,23 @@ +using System.Collections.Generic; +using System.Linq; using mROA.Abstract; -namespace mROA.Implementation.Bootstrap; - -public class FullMixBuilder +namespace mROA.Implementation.Bootstrap { - public List Modules { get; } = []; - - public void Build() + public class FullMixBuilder { - foreach (var module in Modules) - foreach (var injection in Modules) - module.Inject(injection); - } + public List Modules { get; } = new() { }; - public T? GetModule() - { - return Modules.OfType().FirstOrDefault(); + public void Build() + { + foreach (var module in Modules) + foreach (var injection in Modules) + module.Inject(injection); + } + + public T? GetModule() + { + return Modules.OfType().FirstOrDefault(); + } } } \ No newline at end of file diff --git a/mROA/Implementation/CallRequest.cs b/mROA/Implementation/CallRequest.cs index 1709ba7..8a24b42 100644 --- a/mROA/Implementation/CallRequest.cs +++ b/mROA/Implementation/CallRequest.cs @@ -1,24 +1,26 @@ -using System.Text.Json.Serialization; +using System; +using System.Text.Json.Serialization; // ReSharper disable UnusedAutoPropertyAccessor.Global // ReSharper disable AutoPropertyCanBeMadeGetOnly.Global -namespace mROA.Implementation; - -public interface ICallRequest +namespace mROA.Implementation { - Guid Id { get; } - int CommandId { get; } - int ObjectId { get; } - object? Parameter { get; } -} + public interface ICallRequest + { + Guid Id { get; } + int CommandId { get; } + int ObjectId { get; } + object? Parameter { get; } + } -public class DefaultCallRequest : ICallRequest -{ - public Guid Id { get; set; } = Guid.NewGuid(); - public int CommandId { get; init; } - public int ObjectId { get; init; } = -1; + public class DefaultCallRequest : ICallRequest + { + public Guid Id { get; set; } = Guid.NewGuid(); + public int CommandId { get; set; } + public int ObjectId { get; set; } = -1; - [JsonIgnore] - public Type? ParameterType { get; init; } - public object? Parameter { get; set; } + [JsonIgnore] + public Type? ParameterType { get; set; } + public object? Parameter { get; set; } + } } \ No newline at end of file diff --git a/mROA/Implementation/CommandExecution/ExceptionCommandExecution.cs b/mROA/Implementation/CommandExecution/ExceptionCommandExecution.cs index 772fa05..c9d32ab 100644 --- a/mROA/Implementation/CommandExecution/ExceptionCommandExecution.cs +++ b/mROA/Implementation/CommandExecution/ExceptionCommandExecution.cs @@ -1,17 +1,19 @@ -using mROA.Abstract; +using System; +using mROA.Abstract; using mROA.Implementation.Frontend; -namespace mROA.Implementation.CommandExecution; - -public class ExceptionCommandExecution : ICommandExecution +namespace mROA.Implementation.CommandExecution { - public Guid Id { get; init; } - public int ClientId { get; set; } - public int CommandId { get; init; } - public required string Exception { get; set; } - - public RemoteException GetException() + public class ExceptionCommandExecution : ICommandExecution { - return new RemoteException(Exception) { CallRequestId = Id }; + public Guid Id { get; set; } + public int ClientId { get; set; } + public int CommandId { get; set; } + public string Exception { get; set; } + + public RemoteException GetException() + { + return new RemoteException(Exception) { CallRequestId = Id }; + } } } \ No newline at end of file diff --git a/mROA/Implementation/CommandExecution/FinalCommandExecution.cs b/mROA/Implementation/CommandExecution/FinalCommandExecution.cs index 5069911..5fa3f31 100644 --- a/mROA/Implementation/CommandExecution/FinalCommandExecution.cs +++ b/mROA/Implementation/CommandExecution/FinalCommandExecution.cs @@ -1,20 +1,22 @@ -using System.Text.Json.Serialization; +using System; +using System.Text.Json.Serialization; using mROA.Abstract; // ReSharper disable UnusedAutoPropertyAccessor.Global -namespace mROA.Implementation.CommandExecution; - -public class FinalCommandExecution : ICommandExecution +namespace mROA.Implementation.CommandExecution { - public Guid Id { get; init; } - [JsonIgnore] - public int ClientId { get; set; } - [JsonIgnore] - public int CommandId { get; init; } -} + public class FinalCommandExecution : ICommandExecution + { + public Guid Id { get; set; } + [JsonIgnore] + public int ClientId { get; set; } + [JsonIgnore] + public int CommandId { get; set; } + } -public class FinalCommandExecution : FinalCommandExecution -{ - public T? Result { get; init; } + public class FinalCommandExecution : FinalCommandExecution + { + public T? Result { get; set; } + } } \ No newline at end of file diff --git a/mROA/Implementation/CommandExecution/TypedFinalCommandExecution.cs b/mROA/Implementation/CommandExecution/TypedFinalCommandExecution.cs index 813accc..b998737 100644 --- a/mROA/Implementation/CommandExecution/TypedFinalCommandExecution.cs +++ b/mROA/Implementation/CommandExecution/TypedFinalCommandExecution.cs @@ -1,10 +1,12 @@ -using System.Text.Json.Serialization; +using System; +using System.Text.Json.Serialization; -namespace mROA.Implementation.CommandExecution; - -public class TypedFinalCommandExecution : FinalCommandExecution +namespace mROA.Implementation.CommandExecution { - [JsonIgnore] - // ReSharper disable once UnusedAutoPropertyAccessor.Global - public Type? Type { get; set; } + public class TypedFinalCommandExecution : FinalCommandExecution + { + [JsonIgnore] + // ReSharper disable once UnusedAutoPropertyAccessor.Global + public Type? Type { get; set; } + } } \ No newline at end of file diff --git a/mROA/Implementation/CreativeRepresentationModuleProducer.cs b/mROA/Implementation/CreativeRepresentationModuleProducer.cs index 0b79371..667c2f4 100644 --- a/mROA/Implementation/CreativeRepresentationModuleProducer.cs +++ b/mROA/Implementation/CreativeRepresentationModuleProducer.cs @@ -1,40 +1,42 @@ -using mROA.Abstract; +using System; +using mROA.Abstract; -namespace mROA.Implementation; - -public class CreativeRepresentationModuleProducer : IRepresentationModuleProducer +namespace mROA.Implementation { - private Type _reprModuleType; - private IInjectableModule[] _creationModules; - private IConnectionHub? _hub; - - public CreativeRepresentationModuleProducer(IInjectableModule[] creationModules, Type reprModuleType) + public class CreativeRepresentationModuleProducer : IRepresentationModuleProducer { - _creationModules = creationModules; - _reprModuleType = reprModuleType; - } + private Type _reprModuleType; + private IInjectableModule[] _creationModules; + private IConnectionHub? _hub; + + public CreativeRepresentationModuleProducer(IInjectableModule[] creationModules, Type reprModuleType) + { + _creationModules = creationModules; + _reprModuleType = reprModuleType; + } - public void Inject(T dependency) - { - if (dependency is IConnectionHub interactionModule) - _hub = interactionModule; - } + public void Inject(T dependency) + { + if (dependency is IConnectionHub interactionModule) + _hub = interactionModule; + } - public IRepresentationModule Produce(int id) - { - if (_hub == null) - throw new NullReferenceException("Interaction module is null"); + public IRepresentationModule Produce(int id) + { + if (_hub == null) + throw new NullReferenceException("Interaction module is null"); - var produced = - Activator.CreateInstance(_reprModuleType) as IRepresentationModule ?? - throw new Exception("Bad serialization module type"); + var produced = + Activator.CreateInstance(_reprModuleType) as IRepresentationModule ?? + throw new Exception("Bad serialization module type"); - foreach (var creationModule in _creationModules) - produced.Inject(creationModule); + foreach (var creationModule in _creationModules) + produced.Inject(creationModule); - produced.Inject(_hub.GetInteracion(id)); + produced.Inject(_hub.GetInteracion(id)); - return produced; + return produced; + } } } \ No newline at end of file diff --git a/mROA/Implementation/Frontend/JsonFrontendSerialisationModule.cs b/mROA/Implementation/Frontend/JsonFrontendSerialisationModule.cs index dce21a4..98bae9a 100644 --- a/mROA/Implementation/Frontend/JsonFrontendSerialisationModule.cs +++ b/mROA/Implementation/Frontend/JsonFrontendSerialisationModule.cs @@ -1,6 +1,8 @@ -namespace mROA.Implementation.Frontend; +using System; -// public class JsonFrontendSerialisationModule +namespace mROA.Implementation.Frontend +{ + // public class JsonFrontendSerialisationModule // : ISerialisationModule.IFrontendSerialisationModule // { // private IInteractionModule.IFrontendInteractionModule? _interactionModule; @@ -77,8 +79,16 @@ namespace mROA.Implementation.Frontend; // } // } -public class RemoteException(string error) : Exception -{ - public Guid CallRequestId; - public override string Message => $"Error in request {CallRequestId} : {error}"; + public class RemoteException : Exception + { + public Guid CallRequestId; + private readonly string _error; + + public RemoteException(string error) + { + _error = error; + } + + public override string Message => $"Error in request {CallRequestId} : {_error}"; + } } \ No newline at end of file diff --git a/mROA/Implementation/Frontend/NetworkFrontendBridge.cs b/mROA/Implementation/Frontend/NetworkFrontendBridge.cs index a5f4a16..53da9fc 100644 --- a/mROA/Implementation/Frontend/NetworkFrontendBridge.cs +++ b/mROA/Implementation/Frontend/NetworkFrontendBridge.cs @@ -1,43 +1,51 @@ +using System; using System.Net; using System.Net.Sockets; using mROA.Abstract; -namespace mROA.Implementation.Frontend; - -public class NetworkFrontendBridge(IPEndPoint ipEndPoint) : IFrontendBridge +namespace mROA.Implementation.Frontend { - private readonly TcpClient _tcpClient = new(); - private NextGenerationInteractionModule? _interactionModule; - private ISerializationToolkit? _serialization; - - public void Inject(T dependency) + public class NetworkFrontendBridge : IFrontendBridge { - switch (dependency) + private readonly TcpClient _tcpClient = new(); + private NextGenerationInteractionModule? _interactionModule; + private ISerializationToolkit? _serialization; + private readonly IPEndPoint _ipEndPoint; + + public NetworkFrontendBridge(IPEndPoint ipEndPoint) { - case NextGenerationInteractionModule interactionModule: - _interactionModule = interactionModule; - break; - case ISerializationToolkit toolkit: - _serialization = toolkit; - break; + _ipEndPoint = ipEndPoint; } - } - public void Connect() - { - if (_interactionModule is null) - throw new Exception("Interaction module was not injected"); - if (_serialization == null) - throw new NullReferenceException("Serialization toolkit is not initialized"); + public void Inject(T dependency) + { + switch (dependency) + { + case NextGenerationInteractionModule interactionModule: + _interactionModule = interactionModule; + break; + case ISerializationToolkit toolkit: + _serialization = toolkit; + break; + } + } + + public void Connect() + { + if (_interactionModule is null) + throw new Exception("Interaction module was not injected"); + if (_serialization == null) + throw new NullReferenceException("Serialization toolkit is not initialized"); - _tcpClient.Connect(ipEndPoint); - _interactionModule.BaseStream = _tcpClient.GetStream(); - var welcomeMessage = _interactionModule.GetNextMessageReceiving().GetAwaiter().GetResult(); - if (welcomeMessage.SchemaId != MessageType.IdAssigning) - { - throw new Exception($"Incorrect message type. Must be IdAssigning, current : {welcomeMessage.SchemaId.ToString()}"); - } + _tcpClient.Connect(_ipEndPoint); + _interactionModule.BaseStream = _tcpClient.GetStream(); + var welcomeMessage = _interactionModule.GetNextMessageReceiving().GetAwaiter().GetResult(); + if (welcomeMessage.SchemaId != MessageType.IdAssigning) + { + throw new Exception($"Incorrect message type. Must be IdAssigning, current : {welcomeMessage.SchemaId.ToString()}"); + } - TransmissionConfig.OwnershipRepository = new StaticOwnershipRepository(_serialization.Deserialize(welcomeMessage.Data)!.Id); + TransmissionConfig.OwnershipRepository = new StaticOwnershipRepository(_serialization.Deserialize(welcomeMessage.Data)!.Id); + } } } \ No newline at end of file diff --git a/mROA/Implementation/Frontend/RequestExtractor.cs b/mROA/Implementation/Frontend/RequestExtractor.cs index 486a61b..5cfb0b6 100644 --- a/mROA/Implementation/Frontend/RequestExtractor.cs +++ b/mROA/Implementation/Frontend/RequestExtractor.cs @@ -1,88 +1,92 @@ +using System; +using System.Linq; +using System.Threading.Tasks; using mROA.Abstract; using mROA.Implementation.Backend; using mROA.Implementation.CommandExecution; // ReSharper disable MethodHasAsyncOverload -namespace mROA.Implementation.Frontend; - -public class RequestExtractor : IRequestExtractor +namespace mROA.Implementation.Frontend { - private IRepresentationModule? _representationModule; - private IContextRepository? _contextRepository; - private IMethodRepository? _methodRepository; - private IExecuteModule? _executeModule; - private ISerializationToolkit? _serializationToolkit; - - public void Inject(T dependency) + public class RequestExtractor : IRequestExtractor { - switch (dependency) + private IRepresentationModule? _representationModule; + private IContextRepository? _contextRepository; + private IMethodRepository? _methodRepository; + private IExecuteModule? _executeModule; + private ISerializationToolkit? _serializationToolkit; + + public void Inject(T dependency) { - case IExecuteModule executeModule: - _executeModule = executeModule; - break; - case IContextRepository contextRepository: - _contextRepository = contextRepository; - break; - case IMethodRepository methodRepository: - _methodRepository = methodRepository; - break; - case IRepresentationModule representationModule: - _representationModule = representationModule; - break; - case ISerializationToolkit serializationToolkit: - _serializationToolkit = serializationToolkit; - break; - } - } - - public async Task StartExtraction() - { - if (_serializationToolkit == null) - throw new NullReferenceException("Serializing toolkit is null."); - if (_executeModule == null) - throw new NullReferenceException("Execute module is null."); - if (_contextRepository == null) - throw new NullReferenceException("Context repository is null."); - if (_representationModule == null) - throw new NullReferenceException("Representation module is null."); - if (_methodRepository == null) - throw new NullReferenceException("Method repository is null."); - - await Task.Yield(); - - var multiClientOwnershipRepository = TransmissionConfig.OwnershipRepository as MultiClientOwnershipRepository; - multiClientOwnershipRepository?.RegisterOwnership(_representationModule.Id); - - try - { - while (true) + switch (dependency) { - var request = - _representationModule!.GetMessage(messageType: MessageType.CallRequest); - - // Console.WriteLine("Executing {0}", request.Id); - - if (request.Parameter is not null) - { - var parameterType = _methodRepository!.GetMethod(request.CommandId).GetParameters().First() - .ParameterType; - - request.Parameter = _serializationToolkit.Cast(request.Parameter, parameterType); - } - - var result = _executeModule.Execute(request, _contextRepository); - - var resultType = result is FinalCommandExecution - ? MessageType.FinishedCommandExecution - : MessageType.ExceptionCommandExecution; - - _representationModule.PostCallMessage(request.Id, resultType, result, result.GetType()); + case IExecuteModule executeModule: + _executeModule = executeModule; + break; + case IContextRepository contextRepository: + _contextRepository = contextRepository; + break; + case IMethodRepository methodRepository: + _methodRepository = methodRepository; + break; + case IRepresentationModule representationModule: + _representationModule = representationModule; + break; + case ISerializationToolkit serializationToolkit: + _serializationToolkit = serializationToolkit; + break; } } - catch + + public async Task StartExtraction() { + if (_serializationToolkit == null) + throw new NullReferenceException("Serializing toolkit is null."); + if (_executeModule == null) + throw new NullReferenceException("Execute module is null."); + if (_contextRepository == null) + throw new NullReferenceException("Context repository is null."); + if (_representationModule == null) + throw new NullReferenceException("Representation module is null."); + if (_methodRepository == null) + throw new NullReferenceException("Method repository is null."); + + await Task.Yield(); + + var multiClientOwnershipRepository = TransmissionConfig.OwnershipRepository as MultiClientOwnershipRepository; multiClientOwnershipRepository?.RegisterOwnership(_representationModule.Id); + + try + { + while (true) + { + var request = + _representationModule!.GetMessage(messageType: MessageType.CallRequest); + + // Console.WriteLine("Executing {0}", request.Id); + + if (request.Parameter is not null) + { + var parameterType = _methodRepository!.GetMethod(request.CommandId).GetParameters().First() + .ParameterType; + + request.Parameter = _serializationToolkit.Cast(request.Parameter, parameterType); + } + + var result = _executeModule.Execute(request, _contextRepository); + + var resultType = result is FinalCommandExecution + ? MessageType.FinishedCommandExecution + : MessageType.ExceptionCommandExecution; + + _representationModule.PostCallMessage(request.Id, resultType, result, result.GetType()); + } + } + catch + { + multiClientOwnershipRepository?.RegisterOwnership(_representationModule.Id); + } } } } \ No newline at end of file diff --git a/mROA/Implementation/Frontend/StaticOwnershipRepository.cs b/mROA/Implementation/Frontend/StaticOwnershipRepository.cs index bbc0d9b..1739824 100644 --- a/mROA/Implementation/Frontend/StaticOwnershipRepository.cs +++ b/mROA/Implementation/Frontend/StaticOwnershipRepository.cs @@ -1,16 +1,24 @@ using mROA.Abstract; -namespace mROA.Implementation.Frontend; - -public class StaticOwnershipRepository(int id) : IOwnershipRepository +namespace mROA.Implementation.Frontend { - public int GetOwnershipId() + public class StaticOwnershipRepository : IOwnershipRepository { - return id; - } + private readonly int _id; - public int GetHostOwnershipId() - { - return id; + public StaticOwnershipRepository(int id) + { + _id = id; + } + + public int GetOwnershipId() + { + return _id; + } + + public int GetHostOwnershipId() + { + return _id; + } } } \ No newline at end of file diff --git a/mROA/Implementation/IdAssingnment.cs b/mROA/Implementation/IdAssingnment.cs index 5cdb944..dfb634b 100644 --- a/mROA/Implementation/IdAssingnment.cs +++ b/mROA/Implementation/IdAssingnment.cs @@ -1,6 +1,7 @@ -namespace mROA.Implementation; - -public class IdAssingnment +namespace mROA.Implementation { - public int Id { get; set; } + public class IdAssingnment + { + public int Id { get; set; } + } } \ No newline at end of file diff --git a/mROA/Implementation/JsonSerializationToolkit.cs b/mROA/Implementation/JsonSerializationToolkit.cs index 4cc0f75..61a3c7e 100644 --- a/mROA/Implementation/JsonSerializationToolkit.cs +++ b/mROA/Implementation/JsonSerializationToolkit.cs @@ -1,59 +1,61 @@ -using System.Text.Json; +using System; +using System.Text.Json; using mROA.Abstract; -namespace mROA.Implementation; - -public class JsonSerializationToolkit : ISerializationToolkit +namespace mROA.Implementation { - public byte[] Serialize(T objectToSerialize) + public class JsonSerializationToolkit : ISerializationToolkit { - return JsonSerializer.SerializeToUtf8Bytes(objectToSerialize); - } - - public byte[] Serialize(object objectToSerialize, Type type) - { - return JsonSerializer.SerializeToUtf8Bytes(objectToSerialize, type); - } - - public T? Deserialize(byte[] rawData) - { - return JsonSerializer.Deserialize(rawData); - } - - public object? Deserialize(byte[] rawData, Type type) - { - return JsonSerializer.Deserialize(rawData, type); - } - - public T? Deserialize(Span rawData) - { - return JsonSerializer.Deserialize(rawData); - } - - public object? Deserialize(Span rawData, Type type) - { - return JsonSerializer.Deserialize(rawData, type); - } - - public T Cast(object nonCasted) - { - return nonCasted switch + public byte[] Serialize(T objectToSerialize) { - JsonElement jsonElement => jsonElement.Deserialize()!, - T casted => casted, - _ => throw new JsonException("Cannot cast object to type " + typeof(T).FullName) - }; - } + return JsonSerializer.SerializeToUtf8Bytes(objectToSerialize); + } - public object Cast(object nonCasted, Type type) - { - if (nonCasted is JsonElement jsonElement) - return jsonElement.Deserialize(type)!; + public byte[] Serialize(object objectToSerialize, Type type) + { + return JsonSerializer.SerializeToUtf8Bytes(objectToSerialize, type); + } - throw new JsonException("Cannot cast object to type " + type.FullName); - } + public T? Deserialize(byte[] rawData) + { + return JsonSerializer.Deserialize(rawData); + } - public void Inject(T dependency) - { + public object? Deserialize(byte[] rawData, Type type) + { + return JsonSerializer.Deserialize(rawData, type); + } + + public T? Deserialize(Span rawData) + { + return JsonSerializer.Deserialize(rawData); + } + + public object? Deserialize(Span rawData, Type type) + { + return JsonSerializer.Deserialize(rawData, type); + } + + public T Cast(object nonCasted) + { + return nonCasted switch + { + JsonElement jsonElement => jsonElement.Deserialize()!, + T casted => casted, + _ => throw new JsonException("Cannot cast object to type " + typeof(T).FullName) + }; + } + + public object Cast(object nonCasted, Type type) + { + if (nonCasted is JsonElement jsonElement) + return jsonElement.Deserialize(type)!; + + throw new JsonException("Cannot cast object to type " + type.FullName); + } + + public void Inject(T dependency) + { + } } } \ No newline at end of file diff --git a/mROA/Implementation/MethodRepository.cs b/mROA/Implementation/MethodRepository.cs index d429229..020f7fc 100644 --- a/mROA/Implementation/MethodRepository.cs +++ b/mROA/Implementation/MethodRepository.cs @@ -1,43 +1,47 @@ -using System.Reflection; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; using mROA.Abstract; using mROA.Implementation.Attributes; -namespace mROA.Implementation; - -public class MethodRepository : IMethodRepository +namespace mROA.Implementation { - private readonly List _methods = []; - - public MethodInfo GetMethod(int id) + public class MethodRepository : IMethodRepository { - if (_methods.Count <= id) - throw new Exception("Method such registered method"); + private readonly List _methods = new() { }; - return _methods[id]; - } - - public int RegisterMethod(MethodInfo method) - { - _methods.Add(method); - return _methods.Count - 1; - } - - public IEnumerable GetMethods() - { - return _methods; - } - - public void CollectForAssembly(Assembly assembly) - { - var types = assembly.GetTypes().Where(i => i.IsInterface && i.GetCustomAttributes(typeof(SharedObjectInterfaceAttribute), true).Length > 0); - foreach (var type in types) + public MethodInfo GetMethod(int id) { - foreach (var method in type.GetMethods()) - RegisterMethod(method); + if (_methods.Count <= id) + throw new Exception("Method such registered method"); + + return _methods[id]; + } + + public int RegisterMethod(MethodInfo method) + { + _methods.Add(method); + return _methods.Count - 1; + } + + public IEnumerable GetMethods() + { + return _methods; + } + + public void CollectForAssembly(Assembly assembly) + { + var types = assembly.GetTypes().Where(i => i.IsInterface && i.GetCustomAttributes(typeof(SharedObjectInterfaceAttribute), true).Length > 0); + foreach (var type in types) + { + foreach (var method in type.GetMethods()) + RegisterMethod(method); + } + } + public void Inject(T dependency) + { + } } - public void Inject(T dependency) - { - - } } \ No newline at end of file diff --git a/mROA/Implementation/NetworkMessage.cs b/mROA/Implementation/NetworkMessage.cs index 9b524f8..2ccda17 100644 --- a/mROA/Implementation/NetworkMessage.cs +++ b/mROA/Implementation/NetworkMessage.cs @@ -1,18 +1,20 @@ -using System.Text.Json.Serialization; +using System; +using System.Text.Json.Serialization; // ReSharper disable UnusedMember.Global -namespace mROA.Implementation; - -public class NetworkMessage +namespace mROA.Implementation { - public Guid Id { get; init; } - [JsonConverter(typeof(JsonStringEnumConverter))] - public MessageType SchemaId { get; init; } + public class NetworkMessage + { + public Guid Id { get; set; } + [JsonConverter(typeof(JsonStringEnumConverter))] + public MessageType SchemaId { get; set; } - public required byte[] Data { get; init; } -} + public byte[] Data { get; set; } + } -public enum MessageType -{ - Unknown, FinishedCommandExecution, ExceptionCommandExecution, AsyncCancelCommandExecution, CallRequest, IdAssigning + public enum MessageType + { + Unknown, FinishedCommandExecution, ExceptionCommandExecution, AsyncCancelCommandExecution, CallRequest, IdAssigning + } } \ No newline at end of file diff --git a/mROA/Implementation/NextGenerationInteractionModule.cs b/mROA/Implementation/NextGenerationInteractionModule.cs index 0036eda..0f3f253 100644 --- a/mROA/Implementation/NextGenerationInteractionModule.cs +++ b/mROA/Implementation/NextGenerationInteractionModule.cs @@ -1,87 +1,95 @@ -using mROA.Abstract; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using mROA.Abstract; -namespace mROA.Implementation; - -public class NextGenerationInteractionModule : INextGenerationInteractionModule +namespace mROA.Implementation { - private ISerializationToolkit? _serialization; - public int ConnectionId { get; private set; } - public Stream? BaseStream { get; set; } - private Task? _currentReceiving; - private const int BufferSize = ushort.MaxValue; - private readonly Memory _buffer = new byte[BufferSize]; - private readonly List _messageBuffer = new (128); - - - public void Inject(T dependency) + public class NextGenerationInteractionModule : INextGenerationInteractionModule { - switch (dependency) + private ISerializationToolkit? _serialization; + public int ConnectionId { get; private set; } + public Stream? BaseStream { get; set; } + private Task? _currentReceiving; + private const int BufferSize = ushort.MaxValue; + private readonly Memory _buffer = new byte[BufferSize]; + private readonly List _messageBuffer = new (128); + + + public void Inject(T dependency) { - case ISerializationToolkit toolkit: - _serialization = toolkit; - break; - case IIdentityGenerator identityGenerator: - ConnectionId = identityGenerator.GetNextIdentity(); - break; + switch (dependency) + { + case ISerializationToolkit toolkit: + _serialization = toolkit; + break; + case IIdentityGenerator identityGenerator: + ConnectionId = identityGenerator.GetNextIdentity(); + break; + } + } + + public Task GetNextMessageReceiving() + { + if (_currentReceiving != null) return _currentReceiving; + _currentReceiving = Task.Run(GetNextMessage); + return _currentReceiving; + + } + + public async Task PostMessage(NetworkMessage message) + { + if (BaseStream == null) + throw new NullReferenceException("BaseStream is null"); + + if (_serialization == null) + throw new NullReferenceException("Serialization toolkit is not initialized"); + + // Console.WriteLine("Sending {0}", JsonSerializer.Serialize(message)); + + + var rawMessage = _serialization.Serialize(message); + await BaseStream.WriteAsync(BitConverter.GetBytes((ushort)rawMessage.Length).AsMemory(0, sizeof(ushort))); + await BaseStream.WriteAsync(rawMessage); + } + + public void HandleMessage(NetworkMessage message) + { + _messageBuffer.Remove(message); + } + + public NetworkMessage[] UnhandledMessages => _messageBuffer.ToArray(); + public NetworkMessage? FirstByFilter(Predicate predicate) + { + return _messageBuffer.FirstOrDefault(m => predicate(m)); + } + + private async Task GetNextMessage() + { + if (BaseStream == null) + throw new NullReferenceException("BaseStream is null"); + + if (_serialization == null) + throw new NullReferenceException("Serialization toolkit is null"); + + + // Console.WriteLine("Receiving message"); + var firstBit = (byte)BaseStream.ReadByte(); + var secondBit = (byte)BaseStream.ReadByte(); + + var len = BitConverter.ToUInt16(new[] { firstBit, secondBit}); + var localSpan = _buffer.Slice(0, len); + await BaseStream.ReadExactlyAsync(localSpan); + + // Console.WriteLine("Receiving {0}", Encoding.Default.GetString(_buffer[..len])); + + var message = _serialization.Deserialize(localSpan.Span); + _messageBuffer.Add(message!); + _currentReceiving = GetNextMessage(); + + return message!; } } - - - public Task GetNextMessageReceiving() - { - if (_currentReceiving != null) return _currentReceiving; - _currentReceiving = Task.Run(GetNextMessage); - return _currentReceiving; - - } - - public async Task PostMessage(NetworkMessage message) - { - if (BaseStream == null) - throw new NullReferenceException("BaseStream is null"); - - if (_serialization == null) - throw new NullReferenceException("Serialization toolkit is not initialized"); - - // Console.WriteLine("Sending {0}", JsonSerializer.Serialize(message)); - - - var rawMessage = _serialization.Serialize(message); - await BaseStream.WriteAsync(BitConverter.GetBytes((ushort)rawMessage.Length).AsMemory(0, sizeof(ushort))); - await BaseStream.WriteAsync(rawMessage); - } - - public void HandleMessage(NetworkMessage message) - { - _messageBuffer.Remove(message); - } - - public NetworkMessage[] UnhandledMessages => _messageBuffer.ToArray(); - public NetworkMessage? FirstByFilter(Predicate predicate) - { - return _messageBuffer.FirstOrDefault(m => predicate(m)); - } - - private NetworkMessage GetNextMessage() - { - if (BaseStream == null) - throw new NullReferenceException("BaseStream is null"); - - if (_serialization == null) - throw new NullReferenceException("Serialization toolkit is null"); - - - // Console.WriteLine("Receiving message"); - var len = BitConverter.ToUInt16([(byte)BaseStream.ReadByte(), (byte)BaseStream.ReadByte()]); - var localSpan = _buffer.Span.Slice(0, len); - BaseStream.ReadExactly(localSpan); - - // Console.WriteLine("Receiving {0}", Encoding.Default.GetString(_buffer[..len])); - - var message = _serialization.Deserialize(localSpan); - _messageBuffer.Add(message!); - _currentReceiving = Task.Run(GetNextMessage); - - return message!; - } } \ No newline at end of file diff --git a/mROA/Implementation/RemoteContextRepository.cs b/mROA/Implementation/RemoteContextRepository.cs index 37eac71..0b7611d 100644 --- a/mROA/Implementation/RemoteContextRepository.cs +++ b/mROA/Implementation/RemoteContextRepository.cs @@ -1,57 +1,59 @@ -using System.Collections.Frozen; +using System; +using System.Collections.Generic; using mROA.Abstract; -namespace mROA.Implementation; - -public class RemoteContextRepository : IContextRepository +namespace mROA.Implementation { - private IRepresentationModuleProducer? _representationProducer; - public static FrozenDictionary RemoteTypes = FrozenDictionary.Empty; - public int ResisterObject(object o) + public class RemoteContextRepository : IContextRepository { - throw new NotSupportedException(); - } - - public void ClearObject(int id) - { - throw new NotSupportedException(); - } - - public object GetObject(int id) - { - throw new NotSupportedException(); - } - - public T GetObject(int id) - { - if (_representationProducer == null) - throw new NullReferenceException("representation producer is not initialized"); - - if (!RemoteTypes.TryGetValue(typeof(T), out var remoteType)) throw new NotSupportedException(); - var remote = (T)Activator.CreateInstance(remoteType, id, _representationProducer.Produce(TransmissionConfig.OwnershipRepository.GetOwnershipId()))!; - return remote; - } - - public object GetSingleObject(Type type) - { - if (_representationProducer == null) - throw new NullReferenceException("representation producer is not initialized"); - - return Activator.CreateInstance(RemoteTypes[type], -1, _representationProducer.Produce(TransmissionConfig.OwnershipRepository.GetOwnershipId()))!; - } - - public int GetObjectIndex(object o) - { - if (o is RemoteObjectBase remote) + private IRepresentationModuleProducer? _representationProducer; + public static Dictionary RemoteTypes = new(); + public int ResisterObject(object o) { - return remote.Id; + throw new NotSupportedException(); } - throw new NotSupportedException(); - } - public void Inject(T dependency) - { - if (dependency is IRepresentationModuleProducer serialisationModule) - _representationProducer = serialisationModule; + public void ClearObject(int id) + { + throw new NotSupportedException(); + } + + public object GetObject(int id) + { + throw new NotSupportedException(); + } + + public T GetObject(int id) + { + if (_representationProducer == null) + throw new NullReferenceException("representation producer is not initialized"); + + if (!RemoteTypes.TryGetValue(typeof(T), out var remoteType)) throw new NotSupportedException(); + var remote = (T)Activator.CreateInstance(remoteType, id, _representationProducer.Produce(TransmissionConfig.OwnershipRepository.GetOwnershipId()))!; + return remote; + } + + public object GetSingleObject(Type type) + { + if (_representationProducer == null) + throw new NullReferenceException("representation producer is not initialized"); + + return Activator.CreateInstance(RemoteTypes[type], -1, _representationProducer.Produce(TransmissionConfig.OwnershipRepository.GetOwnershipId()))!; + } + + public int GetObjectIndex(object o) + { + if (o is RemoteObjectBase remote) + { + return remote.Id; + } + throw new NotSupportedException(); + } + + public void Inject(T dependency) + { + if (dependency is IRepresentationModuleProducer serialisationModule) + _representationProducer = serialisationModule; + } } } \ No newline at end of file diff --git a/mROA/Implementation/RemoteObjectBase.cs b/mROA/Implementation/RemoteObjectBase.cs index 6a813f2..69e2657 100644 --- a/mROA/Implementation/RemoteObjectBase.cs +++ b/mROA/Implementation/RemoteObjectBase.cs @@ -1,53 +1,64 @@ -using mROA.Abstract; +using System.Threading.Tasks; +using mROA.Abstract; using mROA.Implementation.CommandExecution; // ReSharper disable UnusedMember.Global -namespace mROA.Implementation; - -public abstract class RemoteObjectBase(int id, IRepresentationModule representationModule) +namespace mROA.Implementation { - public int Id => id; - public int OwnerId => representationModule.Id; - - protected async Task GetResultAsync(int methodId, object? parameter = default) + public abstract class RemoteObjectBase { - var request = new DefaultCallRequest - { CommandId = methodId, ObjectId = id, Parameter = parameter, ParameterType = parameter?.GetType() }; - await representationModule.PostCallMessageAsync(request.Id, MessageType.CallRequest, request); + private readonly int _id; + private readonly IRepresentationModule _representationModule; - var successResponse = - representationModule.GetMessageAsync>( - messageType: MessageType.FinishedCommandExecution, requestId: request.Id); - var errorResponse = - representationModule.GetMessageAsync( - messageType: MessageType.ExceptionCommandExecution, requestId: request.Id); - Task.WaitAny(successResponse, errorResponse); + protected RemoteObjectBase(int id, IRepresentationModule representationModule) + { + _id = id; + _representationModule = representationModule; + } - if (successResponse.IsCompletedSuccessfully) - return successResponse.Result.Result!; + public int Id => _id; + public int OwnerId => _representationModule.Id; - throw errorResponse.Result.GetException(); - } + protected async Task GetResultAsync(int methodId, object? parameter = default) + { + var request = new DefaultCallRequest + { CommandId = methodId, ObjectId = _id, Parameter = parameter, ParameterType = parameter?.GetType() }; + await _representationModule.PostCallMessageAsync(request.Id, MessageType.CallRequest, request); - protected async Task CallAsync(int methodId, object? parameter = default) - { - var request = new DefaultCallRequest - { CommandId = methodId, ObjectId = id, Parameter = parameter, ParameterType = parameter?.GetType() }; - await representationModule.PostCallMessageAsync(request.Id, MessageType.CallRequest, request); + var successResponse = + _representationModule.GetMessageAsync>( + messageType: MessageType.FinishedCommandExecution, requestId: request.Id); + var errorResponse = + _representationModule.GetMessageAsync( + messageType: MessageType.ExceptionCommandExecution, requestId: request.Id); + Task.WaitAny(successResponse, errorResponse); - var successResponse = - representationModule.GetMessageAsync( - messageType: MessageType.FinishedCommandExecution, requestId: request.Id); - var errorResponse = - representationModule.GetMessageAsync( - messageType: MessageType.ExceptionCommandExecution, requestId: request.Id); + if (successResponse.IsCompletedSuccessfully) + return successResponse.Result.Result!; - Task.WaitAny(successResponse, errorResponse); + throw errorResponse.Result.GetException(); + } - if (successResponse.IsCompletedSuccessfully) - return; + protected async Task CallAsync(int methodId, object? parameter = default) + { + var request = new DefaultCallRequest + { CommandId = methodId, ObjectId = _id, Parameter = parameter, ParameterType = parameter?.GetType() }; + await _representationModule.PostCallMessageAsync(request.Id, MessageType.CallRequest, request); - throw errorResponse.Result.GetException(); + var successResponse = + _representationModule.GetMessageAsync( + messageType: MessageType.FinishedCommandExecution, requestId: request.Id); + var errorResponse = + _representationModule.GetMessageAsync( + messageType: MessageType.ExceptionCommandExecution, requestId: request.Id); + + Task.WaitAny(successResponse, errorResponse); + + if (successResponse.IsCompletedSuccessfully) + return; + + throw errorResponse.Result.GetException(); + } } } \ No newline at end of file diff --git a/mROA/Implementation/RepresentationModule.cs b/mROA/Implementation/RepresentationModule.cs index 4a119b9..b6e0ce7 100644 --- a/mROA/Implementation/RepresentationModule.cs +++ b/mROA/Implementation/RepresentationModule.cs @@ -1,93 +1,96 @@ -using mROA.Abstract; +using System; +using System.Threading.Tasks; +using mROA.Abstract; -namespace mROA.Implementation; - -public class RepresentationModule : IRepresentationModule +namespace mROA.Implementation { - private ISerializationToolkit? _serialization; - private INextGenerationInteractionModule? _interaction; - - public void Inject(T dependency) + public class RepresentationModule : IRepresentationModule { - switch (dependency) + private ISerializationToolkit? _serialization; + private INextGenerationInteractionModule? _interaction; + + public void Inject(T dependency) { - case ISerializationToolkit toolkit: - _serialization = toolkit; - break; - case INextGenerationInteractionModule interactionModule: - _interaction = interactionModule; - break; - } - } - - public int Id => (_interaction ?? throw new NullReferenceException("Interaction is not initialized")).ConnectionId; - - public async Task GetMessageAsync(Guid? requestId, MessageType? messageType) - { - if (_serialization == null) - throw new NullReferenceException("Serialization toolkit is not initialized"); - - return _serialization.Deserialize(await GetRawMessage(requestId, messageType))!; - } - - public T GetMessage(Guid? requestId = null, MessageType? messageType = null) - { - if (_serialization == null) - throw new NullReferenceException("Serialization toolkit is not initialized"); - - return _serialization.Deserialize(GetRawMessage(requestId, messageType).GetAwaiter().GetResult())!; - } - - public async Task GetRawMessage(Guid? requestId = null, MessageType? messageType = null) - { - if (_interaction == null) - throw new NullReferenceException("Interaction toolkit is not initialized"); - - var fromBuffer = - _interaction.FirstByFilter(message => - (requestId is null || message.Id == requestId) && - (messageType is null || message.SchemaId == messageType)); - - if (fromBuffer == null) - { - while (true) + switch (dependency) { - var message = await _interaction.GetNextMessageReceiving(); - if ((requestId is not null && message.Id != requestId) || - (messageType is not null && message.SchemaId != messageType)) continue; - - _interaction.HandleMessage(message); - return message.Data; + case ISerializationToolkit toolkit: + _serialization = toolkit; + break; + case INextGenerationInteractionModule interactionModule: + _interaction = interactionModule; + break; } } - _interaction.HandleMessage(fromBuffer); - return fromBuffer.Data; - } + public int Id => (_interaction ?? throw new NullReferenceException("Interaction is not initialized")).ConnectionId; - public async Task PostCallMessageAsync(Guid id, MessageType messageType, T payload) where T : notnull - { - await PostCallMessageAsync(id, messageType, payload, typeof(T)); - } - - public async Task PostCallMessageAsync(Guid id, MessageType messageType, object payload, Type payloadType) - { - if (_interaction == null) - throw new NullReferenceException("Interaction toolkit is not initialized"); - if (_serialization == null) - throw new NullReferenceException("Serialization toolkit is not initialized"); + public async Task GetMessageAsync(Guid? requestId, MessageType? messageType) + { + if (_serialization == null) + throw new NullReferenceException("Serialization toolkit is not initialized"); - await _interaction.PostMessage(new NetworkMessage - { Id = id, SchemaId = messageType, Data = _serialization.Serialize(payload, payloadType) }); - } + return _serialization.Deserialize(await GetRawMessage(requestId, messageType))!; + } - public void PostCallMessage(Guid id, MessageType messageType, T payload) where T : notnull - { - PostCallMessageAsync(id, messageType, payload).GetAwaiter().GetResult(); - } + public T GetMessage(Guid? requestId = null, MessageType? messageType = null) + { + if (_serialization == null) + throw new NullReferenceException("Serialization toolkit is not initialized"); + + return _serialization.Deserialize(GetRawMessage(requestId, messageType).GetAwaiter().GetResult())!; + } - public void PostCallMessage(Guid id, MessageType messageType, object payload, Type payloadType) - { - PostCallMessageAsync(id, messageType, payload, payloadType).GetAwaiter().GetResult(); + public async Task GetRawMessage(Guid? requestId = null, MessageType? messageType = null) + { + if (_interaction == null) + throw new NullReferenceException("Interaction toolkit is not initialized"); + + var fromBuffer = + _interaction.FirstByFilter(message => + (requestId is null || message.Id == requestId) && + (messageType is null || message.SchemaId == messageType)); + + if (fromBuffer == null) + { + while (true) + { + var message = await _interaction.GetNextMessageReceiving(); + if ((requestId is not null && message.Id != requestId) || + (messageType is not null && message.SchemaId != messageType)) continue; + + _interaction.HandleMessage(message); + return message.Data; + } + } + + _interaction.HandleMessage(fromBuffer); + return fromBuffer.Data; + } + + public async Task PostCallMessageAsync(Guid id, MessageType messageType, T payload) where T : notnull + { + await PostCallMessageAsync(id, messageType, payload, typeof(T)); + } + + public async Task PostCallMessageAsync(Guid id, MessageType messageType, object payload, Type payloadType) + { + if (_interaction == null) + throw new NullReferenceException("Interaction toolkit is not initialized"); + if (_serialization == null) + throw new NullReferenceException("Serialization toolkit is not initialized"); + + await _interaction.PostMessage(new NetworkMessage + { Id = id, SchemaId = messageType, Data = _serialization.Serialize(payload, payloadType) }); + } + + public void PostCallMessage(Guid id, MessageType messageType, T payload) where T : notnull + { + PostCallMessageAsync(id, messageType, payload).GetAwaiter().GetResult(); + } + + public void PostCallMessage(Guid id, MessageType messageType, object payload, Type payloadType) + { + PostCallMessageAsync(id, messageType, payload, payloadType).GetAwaiter().GetResult(); + } } } \ No newline at end of file diff --git a/mROA/Implementation/SharedObject.cs b/mROA/Implementation/SharedObject.cs index 644b8f4..cf44c46 100644 --- a/mROA/Implementation/SharedObject.cs +++ b/mROA/Implementation/SharedObject.cs @@ -1,101 +1,103 @@ -using System.Text.Json.Serialization; +using System; +using System.Text.Json.Serialization; using mROA.Abstract; // ReSharper disable UnusedMember.Global #pragma warning disable CS8618, CS9264 -namespace mROA.Implementation; - -public static class TransmissionConfig +namespace mROA.Implementation { - private static IContextRepository? _realContextRepository; - private static IContextRepository? _remoteEndpointContextRepository; - private static IOwnershipRepository? _ownershipRepository; - - public static IContextRepository RealContextRepository + public static class TransmissionConfig { - get => _realContextRepository ?? throw new NullReferenceException("RealContextRepository is null"); - set => _realContextRepository = value; - } + private static IContextRepository? _realContextRepository; + private static IContextRepository? _remoteEndpointContextRepository; + private static IOwnershipRepository? _ownershipRepository; - public static IContextRepository RemoteEndpointContextRepository - { - get => _remoteEndpointContextRepository ?? throw new NullReferenceException("RemoteEndpointContextRepository is null"); - set => _remoteEndpointContextRepository = value; - } - - public static IOwnershipRepository OwnershipRepository - { - get => _ownershipRepository ?? throw new NullReferenceException("OwnershipRepository is null"); - set => _ownershipRepository = value; - } - -} - -public class SharedObject where T : notnull -{ - private IContextRepository GetDefaultContextRepository() => - (OwnerId == TransmissionConfig.OwnershipRepository.GetHostOwnershipId() - ? TransmissionConfig.RealContextRepository - : TransmissionConfig.RemoteEndpointContextRepository) ?? - throw new NullReferenceException( - "DefaultContextRepository was not defined"); - - private int _contextId = -2; - private int _ownerId = -1; - - public int OwnerId - { - get + public static IContextRepository RealContextRepository { - _ownerId = _ownerId == -1 ? TransmissionConfig.OwnershipRepository.GetOwnershipId() : _ownerId; - return _ownerId; + get => _realContextRepository ?? throw new NullReferenceException("RealContextRepository is null"); + set => _realContextRepository = value; } - init => _ownerId = value; + + public static IContextRepository RemoteEndpointContextRepository + { + get => _remoteEndpointContextRepository ?? throw new NullReferenceException("RemoteEndpointContextRepository is null"); + set => _remoteEndpointContextRepository = value; + } + + public static IOwnershipRepository OwnershipRepository + { + get => _ownershipRepository ?? throw new NullReferenceException("OwnershipRepository is null"); + set => _ownershipRepository = value; + } + } - // ReSharper disable once MemberCanBePrivate.Global - public int ContextId + public class SharedObject where T : notnull { - // ReSharper disable once UnusedMember.Global - get + private IContextRepository GetDefaultContextRepository() => + (OwnerId == TransmissionConfig.OwnershipRepository.GetHostOwnershipId() + ? TransmissionConfig.RealContextRepository + : TransmissionConfig.RemoteEndpointContextRepository) ?? + throw new NullReferenceException( + "DefaultContextRepository was not defined"); + + private int _contextId = -2; + private int _ownerId = -1; + + public int OwnerId { - if (_contextId != -2) + get + { + _ownerId = _ownerId == -1 ? TransmissionConfig.OwnershipRepository.GetOwnershipId() : _ownerId; + return _ownerId; + } + set => _ownerId = value; + } + + // ReSharper disable once MemberCanBePrivate.Global + public int ContextId + { + // ReSharper disable once UnusedMember.Global + get + { + if (_contextId != -2) + return _contextId; + + _contextId = TransmissionConfig.RealContextRepository.GetObjectIndex(Value); return _contextId; - - _contextId = TransmissionConfig.RealContextRepository.GetObjectIndex(Value); - return _contextId; + } + set + { + _contextId = value; + Value = GetDefaultContextRepository().GetObject(_contextId)!; + } } - init + + [JsonIgnore] public T Value { get; private set; } + + // ReSharper disable once MemberCanBePrivate.Global + // ReSharper disable once UnusedMember.Global + public SharedObject() { - _contextId = value; - Value = GetDefaultContextRepository().GetObject(_contextId)!; } - } - [JsonIgnore] public T Value { get; private init; } - - // ReSharper disable once MemberCanBePrivate.Global - // ReSharper disable once UnusedMember.Global - public SharedObject() - { - } - - // ReSharper disable once UnusedMember.Global - public SharedObject(T value) - { - Value = value; - - if (value is RemoteObjectBase ro) + // ReSharper disable once UnusedMember.Global + public SharedObject(T value) { - _ownerId = ro.OwnerId; - _contextId = ro.Id; + Value = value; + + if (value is RemoteObjectBase ro) + { + _ownerId = ro.OwnerId; + _contextId = ro.Id; + } + else + _ownerId = TransmissionConfig.OwnershipRepository.GetHostOwnershipId(); } - else - _ownerId = TransmissionConfig.OwnershipRepository.GetHostOwnershipId(); + + public static implicit operator T(SharedObject value) => value.Value; + + public static implicit operator SharedObject(T value) => + new(value); } - - public static implicit operator T(SharedObject value) => value.Value; - - public static implicit operator SharedObject(T value) => - new(value); } \ No newline at end of file diff --git a/mROA/Implementation/StaticRepresentationModuleProducer.cs b/mROA/Implementation/StaticRepresentationModuleProducer.cs index 8b0632a..188bfec 100644 --- a/mROA/Implementation/StaticRepresentationModuleProducer.cs +++ b/mROA/Implementation/StaticRepresentationModuleProducer.cs @@ -1,21 +1,23 @@ -using mROA.Abstract; +using System; +using mROA.Abstract; -namespace mROA.Implementation; - -public class StaticRepresentationModuleProducer : IRepresentationModuleProducer +namespace mROA.Implementation { - private IRepresentationModule? _representationModule; + public class StaticRepresentationModuleProducer : IRepresentationModuleProducer + { + private IRepresentationModule? _representationModule; - public IRepresentationModule Produce(int ownership) - { - if (_representationModule == null) - throw new NullReferenceException("The representation module is not initialized."); - return _representationModule; - } + public IRepresentationModule Produce(int ownership) + { + if (_representationModule == null) + throw new NullReferenceException("The representation module is not initialized."); + return _representationModule; + } - public void Inject(T dependency) - { - if (dependency is IRepresentationModule serialisationModule) - _representationModule = serialisationModule; + public void Inject(T dependency) + { + if (dependency is IRepresentationModule serialisationModule) + _representationModule = serialisationModule; + } } } \ No newline at end of file diff --git a/mROA/LegacyExtentions.cs b/mROA/LegacyExtentions.cs new file mode 100644 index 0000000..d35c5a9 --- /dev/null +++ b/mROA/LegacyExtentions.cs @@ -0,0 +1,43 @@ +using System.Collections.Generic; +using global::System; +using global::System.IO; +using global::System.Threading; +using global::System.Threading.Tasks; + +namespace mROA +{ + public static class LegacyExtentions + { + public static async ValueTask ReadExactlyAsync(this Stream stream, byte[] buffer, int offset, int count) + { + return await stream.ReadAtLeastAsyncCore(buffer.AsMemory(offset, count), count, true, default); + } + + public static ValueTask ReadExactlyAsync(this Stream stream, Memory buffer, + CancellationToken cancellationToken = default(CancellationToken)) + { + return stream.ReadAtLeastAsyncCore(buffer, buffer.Length, true, cancellationToken); + } + + private static async ValueTask ReadAtLeastAsyncCore(this Stream stream, + Memory buffer, + int minimumBytes, + bool throwOnEndOfStream, + CancellationToken cancellationToken) + { + int totalRead; + int num; + for (totalRead = 0; totalRead < minimumBytes; totalRead += num) + { + num = await stream.ReadAsync(buffer.Slice(totalRead), cancellationToken).ConfigureAwait(false); + if (num == 0) + { + if (throwOnEndOfStream) + throw new EndOfStreamException(); + return totalRead; + } + } + return totalRead; + } + } +} \ No newline at end of file diff --git a/mROA/mROA.csproj b/mROA/mROA.csproj index 2ab4205..a436d48 100644 --- a/mROA/mROA.csproj +++ b/mROA/mROA.csproj @@ -1,8 +1,7 @@  - net9.0 - enable + netstandard2.1 enable mROA 2.0.0 @@ -12,6 +11,11 @@ https://github.com/YaslePoy/mROA git RPC + 9 + + + +