билдится на старом дотнете
This commit is contained in:
@@ -2,9 +2,11 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net9.0</TargetFramework>
|
<TargetFramework>netstandard2.1</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
|
<LangVersion>9</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -1,28 +1,30 @@
|
|||||||
using Example.Shared;
|
using System;
|
||||||
|
using Example.Shared;
|
||||||
using mROA.Implementation.Attributes;
|
using mROA.Implementation.Attributes;
|
||||||
|
|
||||||
namespace Example.Backend;
|
namespace Example.Backend
|
||||||
|
|
||||||
[SharedObjectSingleton]
|
|
||||||
public class LoadTestImp : ILoadTest
|
|
||||||
{
|
{
|
||||||
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)
|
public int Last(int next)
|
||||||
{
|
{
|
||||||
return next - 1;
|
return next - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void C()
|
public void C()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void A()
|
public void A()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using Example.Shared;
|
using Example.Shared;
|
||||||
|
|
||||||
namespace Example.Backend;
|
namespace Example.Backend
|
||||||
|
|
||||||
public class Page : IPage
|
|
||||||
{
|
{
|
||||||
public string Text;
|
public class Page : IPage
|
||||||
public byte[] GetData()
|
|
||||||
{
|
{
|
||||||
return Encoding.UTF8.GetBytes(Text);
|
public string Text;
|
||||||
|
public byte[] GetData()
|
||||||
|
{
|
||||||
|
return Encoding.UTF8.GetBytes(Text);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+14
-12
@@ -1,20 +1,22 @@
|
|||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Example.Shared;
|
using Example.Shared;
|
||||||
using mROA.Implementation;
|
using mROA.Implementation;
|
||||||
|
|
||||||
namespace Example.Backend;
|
namespace Example.Backend
|
||||||
|
|
||||||
|
|
||||||
public class Printer : IPrinter
|
|
||||||
{
|
{
|
||||||
public string Name;
|
public class Printer : IPrinter
|
||||||
public string GetName()
|
|
||||||
{
|
{
|
||||||
return Name;
|
public string Name;
|
||||||
}
|
public string GetName()
|
||||||
|
{
|
||||||
|
return Name;
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<SharedObject<IPage>> Print(string text, CancellationToken cancellationToken = default)
|
public async Task<SharedObject<IPage>> Print(string text, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
// throw new Exception("The method or operation is not implemented.");
|
// throw new Exception("The method or operation is not implemented.");
|
||||||
return new Page {Text = text};
|
return new Page {Text = text};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,40 +1,44 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Example.Shared;
|
using Example.Shared;
|
||||||
using mROA.Implementation;
|
using mROA.Implementation;
|
||||||
using mROA.Implementation.Attributes;
|
using mROA.Implementation.Attributes;
|
||||||
|
|
||||||
namespace Example.Backend;
|
namespace Example.Backend
|
||||||
|
|
||||||
[SharedObjectSingleton]
|
|
||||||
public class PrinterFactory : IPrinterFactory
|
|
||||||
{
|
{
|
||||||
private List<IPrinter> _printers = new();
|
[SharedObjectSingleton]
|
||||||
|
public class PrinterFactory : IPrinterFactory
|
||||||
public SharedObject<IPrinter> Create(string printerName)
|
|
||||||
{
|
{
|
||||||
Console.WriteLine("Creating printer");
|
private List<IPrinter> _printers = new List<IPrinter>();
|
||||||
return new Printer { Name = printerName };
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Register(SharedObject<IPrinter> printer)
|
public SharedObject<IPrinter> Create(string printerName)
|
||||||
{
|
{
|
||||||
_printers.Add(printer.Value);
|
Console.WriteLine("Creating printer");
|
||||||
Console.WriteLine("Registered printer");
|
return new Printer { Name = printerName };
|
||||||
}
|
}
|
||||||
|
|
||||||
public SharedObject<IPrinter> GetPrinterByName(string printerName)
|
public void Register(SharedObject<IPrinter> printer)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Getting printer");
|
_printers.Add(printer.Value);
|
||||||
return new SharedObject<IPrinter>(_printers.Find(i => i.GetName() == printerName)!);
|
Console.WriteLine("Registered printer");
|
||||||
}
|
}
|
||||||
|
|
||||||
public SharedObject<IPrinter> GetFirstPrinter()
|
public SharedObject<IPrinter> GetPrinterByName(string printerName)
|
||||||
{
|
{
|
||||||
return new SharedObject<IPrinter>(_printers.First());
|
Console.WriteLine("Getting printer");
|
||||||
}
|
return new SharedObject<IPrinter>(_printers.Find(i => i.GetName() == printerName)!);
|
||||||
|
}
|
||||||
|
|
||||||
public string[] CollectAllNames()
|
public SharedObject<IPrinter> GetFirstPrinter()
|
||||||
{
|
{
|
||||||
Console.WriteLine("Collecting all printers");
|
return new SharedObject<IPrinter>(_printers.First());
|
||||||
return _printers.Select(i => i.GetName()).ToArray();
|
}
|
||||||
|
|
||||||
|
public string[] CollectAllNames()
|
||||||
|
{
|
||||||
|
Console.WriteLine("Collecting all printers");
|
||||||
|
return _printers.Select(i => i.GetName()).ToArray();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+35
-29
@@ -7,37 +7,43 @@ using mROA.Implementation.Backend;
|
|||||||
using mROA.Implementation.Bootstrap;
|
using mROA.Implementation.Bootstrap;
|
||||||
using mROA.Implementation.Frontend;
|
using mROA.Implementation.Frontend;
|
||||||
|
|
||||||
|
class Program
|
||||||
var builder = new FullMixBuilder();
|
|
||||||
builder.UseJsonSerialisation();
|
|
||||||
builder.Modules.Add(new BackendIdentityGenerator());
|
|
||||||
builder.UseNetworkGateway(new IPEndPoint(IPAddress.Loopback, 4567), typeof(NextGenerationInteractionModule),
|
|
||||||
builder.GetModule<IIdentityGenerator>()!);
|
|
||||||
|
|
||||||
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 =>
|
|
||||||
{
|
{
|
||||||
var repo = new ContextRepository();
|
public static void Main(string[] args)
|
||||||
repo.FillSingletons(typeof(PrinterFactory).Assembly);
|
{
|
||||||
return repo;
|
var builder = new FullMixBuilder();
|
||||||
}));
|
builder.UseJsonSerialisation();
|
||||||
builder.SetupMethodsRepository(new CoCodegenMethodRepository());
|
builder.Modules.Add(new BackendIdentityGenerator());
|
||||||
builder.Modules.Add(new CreativeRepresentationModuleProducer([builder.GetModule<JsonSerializationToolkit>()!],
|
builder.UseNetworkGateway(new IPEndPoint(IPAddress.Loopback, 4567), typeof(NextGenerationInteractionModule),
|
||||||
typeof(RepresentationModule)));
|
builder.GetModule<IIdentityGenerator>()!);
|
||||||
|
|
||||||
builder.Build();
|
builder.Modules.Add(new ConnectionHub());
|
||||||
new RemoteTypeBinder();
|
builder.Modules.Add(new HubRequestExtractor(typeof(RequestExtractor)));
|
||||||
|
|
||||||
TransmissionConfig.RealContextRepository = builder.GetModule<MultiClientContextRepository>();
|
builder.UseBasicExecution();
|
||||||
TransmissionConfig.RemoteEndpointContextRepository = builder.GetModule<RemoteContextRepository>();
|
|
||||||
TransmissionConfig.OwnershipRepository = new MultiClientOwnershipRepository();
|
|
||||||
|
|
||||||
var gateway = builder.GetModule<IGatewayModule>();
|
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<JsonSerializationToolkit>()! },
|
||||||
|
typeof(RepresentationModule)));
|
||||||
|
|
||||||
gateway.Run();
|
builder.Build();
|
||||||
|
new RemoteTypeBinder();
|
||||||
|
|
||||||
|
TransmissionConfig.RealContextRepository = builder.GetModule<MultiClientContextRepository>();
|
||||||
|
TransmissionConfig.RemoteEndpointContextRepository = builder.GetModule<RemoteContextRepository>();
|
||||||
|
TransmissionConfig.OwnershipRepository = new MultiClientOwnershipRepository();
|
||||||
|
|
||||||
|
var gateway = builder.GetModule<IGatewayModule>();
|
||||||
|
|
||||||
|
gateway.Run();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,28 +1,32 @@
|
|||||||
using Example.Shared;
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Example.Shared;
|
||||||
using mROA.Implementation;
|
using mROA.Implementation;
|
||||||
|
|
||||||
namespace Example.Frontend;
|
namespace Example.Frontend
|
||||||
|
|
||||||
public class ClientBasedPrinter : IPrinter
|
|
||||||
{
|
{
|
||||||
public string GetName()
|
public class ClientBasedPrinter : IPrinter
|
||||||
{
|
{
|
||||||
Console.WriteLine("ClientBasedPrinter called from server!!!!!!!!!!! Vova likes that:)");
|
public string GetName()
|
||||||
return "ClientBasedPrinter from mroa";
|
{
|
||||||
|
Console.WriteLine("ClientBasedPrinter called from server!!!!!!!!!!! Vova likes that:)");
|
||||||
|
return "ClientBasedPrinter from mroa";
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<SharedObject<IPage>> Print(string text, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Printed: {text}");
|
||||||
|
await Task.Yield();
|
||||||
|
return new ClientBasedPage();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<SharedObject<IPage>> Print(string text, CancellationToken cancellationToken)
|
public class ClientBasedPage : IPage
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Printed: {text}");
|
public byte[] GetData()
|
||||||
await Task.Yield();
|
{
|
||||||
return new ClientBasedPage();
|
return new byte[] { 1, 2, 3 };
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public class ClientBasedPage : IPage
|
|
||||||
{
|
|
||||||
public byte[] GetData()
|
|
||||||
{
|
|
||||||
return [1, 2, 3];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,9 +2,11 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net9.0</TargetFramework>
|
<TargetFramework>netstandard2.1</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
|
<LangVersion>9</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
+61
-53
@@ -1,6 +1,8 @@
|
|||||||
using System.Diagnostics;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
using Example.Frontend;
|
using Example.Frontend;
|
||||||
using Example.Shared;
|
using Example.Shared;
|
||||||
using mROA.Codegen;
|
using mROA.Codegen;
|
||||||
@@ -9,71 +11,77 @@ using mROA.Implementation.Backend;
|
|||||||
using mROA.Implementation.Bootstrap;
|
using mROA.Implementation.Bootstrap;
|
||||||
using mROA.Implementation.Frontend;
|
using mROA.Implementation.Frontend;
|
||||||
|
|
||||||
var builder = new FullMixBuilder();
|
class Program
|
||||||
new RemoteTypeBinder();
|
{
|
||||||
builder.Modules.Add(new JsonSerializationToolkit());
|
public static void Main(string[] args)
|
||||||
builder.Modules.Add(new RemoteContextRepository());
|
{
|
||||||
builder.Modules.Add(new NextGenerationInteractionModule());
|
var builder = new FullMixBuilder();
|
||||||
builder.Modules.Add(new RepresentationModule());
|
new RemoteTypeBinder();
|
||||||
builder.Modules.Add(new NetworkFrontendBridge(new IPEndPoint(IPAddress.Loopback, 4567)));
|
builder.Modules.Add(new JsonSerializationToolkit());
|
||||||
builder.Modules.Add(new StaticRepresentationModuleProducer());
|
builder.Modules.Add(new RemoteContextRepository());
|
||||||
builder.Modules.Add(new RequestExtractor());
|
builder.Modules.Add(new NextGenerationInteractionModule());
|
||||||
builder.Modules.Add(new BasicExecutionModule());
|
builder.Modules.Add(new RepresentationModule());
|
||||||
builder.Modules.Add(new CoCodegenMethodRepository());
|
builder.Modules.Add(new NetworkFrontendBridge(new IPEndPoint(IPAddress.Loopback, 4567)));
|
||||||
builder.UseCollectableContextRepository();
|
builder.Modules.Add(new StaticRepresentationModuleProducer());
|
||||||
builder.Build();
|
builder.Modules.Add(new RequestExtractor());
|
||||||
|
builder.Modules.Add(new BasicExecutionModule());
|
||||||
|
builder.Modules.Add(new CoCodegenMethodRepository());
|
||||||
|
builder.UseCollectableContextRepository();
|
||||||
|
builder.Build();
|
||||||
|
|
||||||
|
|
||||||
TransmissionConfig.RealContextRepository = builder.GetModule<ContextRepository>();
|
TransmissionConfig.RealContextRepository = builder.GetModule<ContextRepository>();
|
||||||
TransmissionConfig.RemoteEndpointContextRepository = builder.GetModule<RemoteContextRepository>();
|
TransmissionConfig.RemoteEndpointContextRepository = builder.GetModule<RemoteContextRepository>();
|
||||||
|
|
||||||
builder.GetModule<NetworkFrontendBridge>()!.Connect();
|
builder.GetModule<NetworkFrontendBridge>()!.Connect();
|
||||||
_ = builder.GetModule<RequestExtractor>()!.StartExtraction();
|
_ = builder.GetModule<RequestExtractor>()!.StartExtraction();
|
||||||
Console.WriteLine(TransmissionConfig.OwnershipRepository.GetOwnershipId());
|
Console.WriteLine(TransmissionConfig.OwnershipRepository.GetOwnershipId());
|
||||||
var context = builder.GetModule<RemoteContextRepository>();
|
var context = builder.GetModule<RemoteContextRepository>();
|
||||||
|
|
||||||
var factory = context.GetSingleObject(typeof(IPrinterFactory)) as IPrinterFactory;
|
var factory = context.GetSingleObject(typeof(IPrinterFactory)) as IPrinterFactory;
|
||||||
|
|
||||||
//правильный порядок команд 8-5-10-7
|
//правильный порядок команд 8-5-10-7
|
||||||
var printer = factory.Create("Test");
|
var printer = factory.Create("Test");
|
||||||
Console.WriteLine("Printer created");
|
Console.WriteLine("Printer created");
|
||||||
Thread.Sleep(100);
|
Thread.Sleep(100);
|
||||||
|
|
||||||
var name = printer.Value.GetName();
|
var name = printer.Value.GetName();
|
||||||
Console.WriteLine("Printer name : {0}", name);
|
Console.WriteLine("Printer name : {0}", name);
|
||||||
Thread.Sleep(100);
|
Thread.Sleep(100);
|
||||||
|
|
||||||
factory.Register(new SharedObject<IPrinter>(new ClientBasedPrinter()));
|
factory.Register(new SharedObject<IPrinter>(new ClientBasedPrinter()));
|
||||||
Console.WriteLine("Registered printer");
|
Console.WriteLine("Registered printer");
|
||||||
Thread.Sleep(100);
|
Thread.Sleep(100);
|
||||||
|
|
||||||
|
|
||||||
var registred = factory.GetFirstPrinter();
|
var registred = factory.GetFirstPrinter();
|
||||||
Console.WriteLine("First printer");
|
Console.WriteLine("First printer");
|
||||||
Thread.Sleep(100);
|
Thread.Sleep(100);
|
||||||
|
|
||||||
Console.WriteLine(registred.Value);
|
Console.WriteLine(registred.Value);
|
||||||
Console.WriteLine("Collecting all printers");
|
Console.WriteLine("Collecting all printers");
|
||||||
var names = factory.CollectAllNames();
|
var names = factory.CollectAllNames();
|
||||||
Thread.Sleep(100);
|
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 page = printer.Value.Print("Test Page", new CancellationToken()).GetAwaiter().GetResult();
|
||||||
var data = page.Value.GetData();
|
var data = page.Value.GetData();
|
||||||
Console.WriteLine("Data : {0}", Encoding.UTF8.GetString(data));
|
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;
|
const int iterations = 10000;
|
||||||
var timer = Stopwatch.StartNew();
|
var timer = Stopwatch.StartNew();
|
||||||
var x = 0;
|
var x = 0;
|
||||||
for (int i = 0; i < iterations; i++)
|
for (int i = 0; i < iterations; i++)
|
||||||
{
|
{
|
||||||
x = loadSingleton.Next(x);
|
x = loadSingleton.Next(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
timer.Stop();
|
timer.Stop();
|
||||||
Console.WriteLine("X is {0}", x);
|
Console.WriteLine("X is {0}", x);
|
||||||
Console.WriteLine("Time : {0}", timer.Elapsed.TotalMilliseconds);
|
Console.WriteLine("Time : {0}", timer.Elapsed.TotalMilliseconds);
|
||||||
Console.WriteLine($"Time per call: {timer.Elapsed.TotalMilliseconds / iterations} ms");
|
Console.WriteLine($"Time per call: {timer.Elapsed.TotalMilliseconds / iterations} ms");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net9.0</TargetFramework>
|
<TargetFramework>netstandard2.1</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
|
<LangVersion>9</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
using mROA.Implementation.Attributes;
|
using mROA.Implementation.Attributes;
|
||||||
|
|
||||||
namespace Example.Shared;
|
namespace Example.Shared
|
||||||
|
|
||||||
[SharedObjectInterface]
|
|
||||||
public interface ILoadTest
|
|
||||||
{
|
{
|
||||||
int Next(int last);
|
[SharedObjectInterface]
|
||||||
int Last(int next);
|
public interface ILoadTest
|
||||||
void C();
|
{
|
||||||
void A();
|
int Next(int last);
|
||||||
|
int Last(int next);
|
||||||
|
void C();
|
||||||
|
void A();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
using mROA.Implementation.Attributes;
|
using mROA.Implementation.Attributes;
|
||||||
|
|
||||||
namespace Example.Shared;
|
namespace Example.Shared
|
||||||
|
|
||||||
[SharedObjectInterface]
|
|
||||||
public interface IPage
|
|
||||||
{
|
{
|
||||||
byte[] GetData();
|
[SharedObjectInterface]
|
||||||
|
public interface IPage
|
||||||
|
{
|
||||||
|
byte[] GetData();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,15 @@
|
|||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using mROA.Implementation;
|
using mROA.Implementation;
|
||||||
using mROA.Implementation.Attributes;
|
using mROA.Implementation.Attributes;
|
||||||
|
|
||||||
namespace Example.Shared;
|
namespace Example.Shared
|
||||||
|
|
||||||
[SharedObjectInterface]
|
|
||||||
public interface IPrinter
|
|
||||||
{
|
{
|
||||||
string GetName();
|
[SharedObjectInterface]
|
||||||
Task<SharedObject<IPage>> Print(string text, CancellationToken cancellationToken);
|
public interface IPrinter
|
||||||
|
{
|
||||||
|
string GetName();
|
||||||
|
Task<SharedObject<IPage>> Print(string text, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,15 +1,16 @@
|
|||||||
using mROA.Implementation;
|
using mROA.Implementation;
|
||||||
using mROA.Implementation.Attributes;
|
using mROA.Implementation.Attributes;
|
||||||
|
|
||||||
namespace Example.Shared;
|
namespace Example.Shared
|
||||||
|
|
||||||
[SharedObjectInterface]
|
|
||||||
public interface IPrinterFactory
|
|
||||||
{
|
{
|
||||||
SharedObject<IPrinter> Create(string printerName);
|
[SharedObjectInterface]
|
||||||
void Register(SharedObject<IPrinter> printer);
|
public interface IPrinterFactory
|
||||||
SharedObject<IPrinter> GetPrinterByName(string printerName);
|
{
|
||||||
SharedObject<IPrinter> GetFirstPrinter();
|
SharedObject<IPrinter> Create(string printerName);
|
||||||
string[] CollectAllNames();
|
void Register(SharedObject<IPrinter> printer);
|
||||||
|
SharedObject<IPrinter> GetPrinterByName(string printerName);
|
||||||
|
SharedObject<IPrinter> GetFirstPrinter();
|
||||||
|
string[] CollectAllNames();
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+42
-38
@@ -1,50 +1,54 @@
|
|||||||
using BenchmarkDotNet.Attributes;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
using BenchmarkDotNet.Running;
|
using BenchmarkDotNet.Running;
|
||||||
|
|
||||||
namespace mROA.Benchmark;
|
namespace mROA.Benchmark
|
||||||
|
|
||||||
class Program
|
|
||||||
{
|
{
|
||||||
static void Main(string[] args)
|
class Program
|
||||||
{
|
{
|
||||||
Console.WriteLine("Hello, World!");
|
static void Main(string[] args)
|
||||||
var summary = BenchmarkRunner.Run<CollectionsSpeed>();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CollectionsSpeed
|
|
||||||
{
|
|
||||||
private const int N = 1000;
|
|
||||||
|
|
||||||
private readonly List<int> _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++)
|
|
||||||
{
|
{
|
||||||
sum += _array[i];
|
Console.WriteLine("Hello, World!");
|
||||||
|
var summary = BenchmarkRunner.Run<CollectionsSpeed>();
|
||||||
|
|
||||||
}
|
}
|
||||||
return sum;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Benchmark]
|
public class CollectionsSpeed
|
||||||
public int ImmutableArray()
|
|
||||||
{
|
{
|
||||||
var sum = 0;
|
private const int N = 1000;
|
||||||
for (int i = 0; i < N; i++)
|
|
||||||
|
private readonly List<int> _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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net9.0</TargetFramework>
|
<TargetFramework>netstandard2.1</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -25,8 +25,7 @@
|
|||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.3.0" />
|
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.8.0" />
|
||||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.3.0" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
+275
-213
@@ -7,19 +7,19 @@ using Microsoft.CodeAnalysis.CSharp.Syntax;
|
|||||||
using Microsoft.CodeAnalysis.Text;
|
using Microsoft.CodeAnalysis.Text;
|
||||||
|
|
||||||
|
|
||||||
namespace mROA.Codegen;
|
namespace mROA.Codegen
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 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.
|
|
||||||
/// </summary>
|
|
||||||
[Generator]
|
|
||||||
public class mROASourceGenerator : IIncrementalGenerator
|
|
||||||
{
|
{
|
||||||
private const string Namespace = "mROA.Implementation";
|
/// <summary>
|
||||||
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.
|
||||||
|
/// </summary>
|
||||||
|
[Generator]
|
||||||
|
public class mROASourceGenerator : ISourceGenerator
|
||||||
|
{
|
||||||
|
private const string Namespace = "mROA.Implementation";
|
||||||
|
private const string AttributeName = "SharedObjectInterafceAttribute";
|
||||||
|
|
||||||
private const string AttributeSourceCode = $@"// <auto-generated/>
|
private const string AttributeSourceCode = $@"// <auto-generated/>
|
||||||
|
|
||||||
namespace {Namespace}
|
namespace {Namespace}
|
||||||
{{
|
{{
|
||||||
@@ -29,151 +29,151 @@ namespace {Namespace}
|
|||||||
}}
|
}}
|
||||||
}}";
|
}}";
|
||||||
|
|
||||||
public void Initialize(IncrementalGeneratorInitializationContext context)
|
// public void Initialize(IncrementalGeneratorInitializationContext context)
|
||||||
{
|
// {
|
||||||
// Filter classes annotated with the [Report] attribute. Only filtered Syntax Nodes can trigger code generation.
|
// // Filter classes annotated with the [Report] attribute. Only filtered Syntax Nodes can trigger code generation.
|
||||||
var provider = context.SyntaxProvider
|
// var provider = context.SyntaxProvider
|
||||||
.CreateSyntaxProvider(
|
// .CreateSyntaxProvider(
|
||||||
(s, _) => s is InterfaceDeclarationSyntax,
|
// (s, _) => s is InterfaceDeclarationSyntax,
|
||||||
(ctx, _) => GetClassDeclarationForSourceGen(ctx))
|
// (ctx, _) => GetClassDeclarationForSourceGen(ctx))
|
||||||
.Where(t => t.reportAttributeFound)
|
// .Where(t => t.reportAttributeFound)
|
||||||
.Select((t, _) => t.Item1);
|
// .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.
|
/// <summary>
|
||||||
context.RegisterSourceOutput(context.CompilationProvider.Combine(provider.Collect()),
|
/// Checks whether the Node is annotated with the [Report] attribute and maps syntax context to the specific node type (ClassDeclarationSyntax).
|
||||||
((ctx, t) => GenerateCode(ctx, t.Left, t.Right)));
|
/// </summary>
|
||||||
}
|
/// <param name="context">Syntax context, based on CreateSyntaxProvider predicate</param>
|
||||||
|
/// <returns>The specific cast and whether the attribute was found.</returns>
|
||||||
|
// 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);
|
||||||
|
// }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks whether the Node is annotated with the [Report] attribute and maps syntax context to the specific node type (ClassDeclarationSyntax).
|
/// Generate code action.
|
||||||
/// </summary>
|
/// It will be executed on specific nodes (ClassDeclarationSyntax annotated with the [Report] attribute) changed by the user.
|
||||||
/// <param name="context">Syntax context, based on CreateSyntaxProvider predicate</param>
|
/// </summary>
|
||||||
/// <returns>The specific cast and whether the attribute was found.</returns>
|
/// <param name="context">Source generation context used to add source files.</param>
|
||||||
private static (InterfaceDeclarationSyntax, bool reportAttributeFound) GetClassDeclarationForSourceGen(
|
/// <param name="compilation">Compilation used to provide access to the Semantic Model.</param>
|
||||||
GeneratorSyntaxContext context)
|
/// <param name="classes">Nodes annotated with the [Report] attribute that trigger the generate action.</param>
|
||||||
{
|
private void GenerateCode(GeneratorExecutionContext context, Compilation compilation,
|
||||||
var classDeclarationSyntax = (InterfaceDeclarationSyntax)context.Node;
|
ImmutableArray<InterfaceDeclarationSyntax> classes)
|
||||||
|
|
||||||
// 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)
|
var methods = new List<(string, IMethodSymbol)>();
|
||||||
continue; // if we can't get the symbol, ignore it
|
var frontendContextRepo = new List<string>();
|
||||||
|
// Go through all filtered class declarations.
|
||||||
string attributeName = attributeSymbol.ContainingType.ToDisplayString();
|
var declarations = classes.ToList().OrderBy(i => i.Identifier.Text).ToList();
|
||||||
|
foreach (var classDeclarationSyntax in declarations)
|
||||||
// Check the full name of the [Report] attribute.
|
|
||||||
if (attributeName == "mROA.Implementation.Attributes.SharedObjectInterfaceAttribute")
|
|
||||||
return (classDeclarationSyntax, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (classDeclarationSyntax, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Generate code action.
|
|
||||||
/// It will be executed on specific nodes (ClassDeclarationSyntax annotated with the [Report] attribute) changed by the user.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="context">Source generation context used to add source files.</param>
|
|
||||||
/// <param name="compilation">Compilation used to provide access to the Semantic Model.</param>
|
|
||||||
/// <param name="classes">Nodes annotated with the [Report] attribute that trigger the generate action.</param>
|
|
||||||
private void GenerateCode(SourceProductionContext context, Compilation compilation,
|
|
||||||
ImmutableArray<InterfaceDeclarationSyntax> classes)
|
|
||||||
{
|
|
||||||
var methods = new List<(string, IMethodSymbol)>();
|
|
||||||
var frontendContextRepo = new List<string>();
|
|
||||||
// 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<IMethodSymbol>().OrderBy(i => i.Name);
|
|
||||||
|
|
||||||
var originalName = className;
|
|
||||||
// Build up the source code
|
|
||||||
className = className.TrimStart('I') + "RemoteEndpoint";
|
|
||||||
|
|
||||||
|
|
||||||
var methodsText = new List<string>();
|
|
||||||
|
|
||||||
foreach (var method in methodBody)
|
|
||||||
{
|
{
|
||||||
var index = methods.Count;
|
// We need to get semantic model of the class to retrieve metadata.
|
||||||
methods.Add((namespaceName + "." + originalName, method));
|
var semanticModel = compilation.GetSemanticModel(classDeclarationSyntax.SyntaxTree);
|
||||||
var sb = new StringBuilder();
|
|
||||||
|
|
||||||
|
|
||||||
bool isAsync = method.ReturnType.Name == "Task";
|
// Symbols allow us to get the compile-time information.
|
||||||
bool isVoid = method.ReturnType.Name == "Void" || method.ReturnType.ToString() == "Task";
|
if (semanticModel.GetDeclaredSymbol(classDeclarationSyntax) is not INamedTypeSymbol classSymbol)
|
||||||
bool isParametrized = method.Parameters.Length == 1 && !isAsync ||
|
continue;
|
||||||
method.Parameters.Length == 2 && isAsync;
|
|
||||||
|
|
||||||
|
|
||||||
//Creating signature
|
var namespaceName = classSymbol.ContainingNamespace.ToDisplayString();
|
||||||
sb.AppendLine("public" + (isAsync
|
|
||||||
? " async "
|
// 'Identifier' means the token of the node. Get class name from the syntax node.
|
||||||
: " ") +
|
var className = classDeclarationSyntax.Identifier.Text;
|
||||||
$"{method.ReturnType.ToDisplayString()} {method.Name}({string.Join(", ", method.Parameters.Select(ToFullString))}){{");
|
|
||||||
|
// Go through all class members with a particular type (property) to generate method lines.
|
||||||
|
var methodBody = classSymbol.GetMembers()
|
||||||
|
.OfType<IMethodSymbol>().OrderBy(i => i.Name);
|
||||||
|
|
||||||
|
var originalName = className;
|
||||||
|
// Build up the source code
|
||||||
|
className = className.TrimStart('I') + "RemoteEndpoint";
|
||||||
|
|
||||||
|
|
||||||
var prefix = isAsync ? "await " : "";
|
var methodsText = new List<string>();
|
||||||
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)
|
foreach (var method in methodBody)
|
||||||
prefix = "return " + prefix;
|
{
|
||||||
|
var index = methods.Count;
|
||||||
// if (method.ReturnType.OriginalDefinition.ToString() == "System.Threading.Tasks.Task<TResult>")
|
methods.Add((namespaceName + "." + originalName, method));
|
||||||
// {
|
var sb = new StringBuilder();
|
||||||
// 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<FinalCommandExecution>(defaultCallRequestCodegen.CallRequestId).Wait();");
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// sb.AppendLine("\t}");
|
|
||||||
|
|
||||||
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 = $@"// <auto-generated/>
|
|
||||||
|
//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<TResult>")
|
||||||
|
// {
|
||||||
|
// 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<FinalCommandExecution>(defaultCallRequestCodegen.CallRequestId).Wait();");
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// sb.AppendLine("\t}");
|
||||||
|
|
||||||
|
sb.AppendLine("\t\t\t" + prefix + caller + postfix + ";");
|
||||||
|
|
||||||
|
sb.AppendLine("\t\t}");
|
||||||
|
|
||||||
|
methodsText.Add(sb.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
var code = $@"// <auto-generated/>
|
||||||
|
|
||||||
using mROA;
|
using mROA;
|
||||||
using System;
|
using System;
|
||||||
@@ -181,106 +181,168 @@ using mROA.Implementation;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
|
|
||||||
namespace {namespaceName};
|
namespace {namespaceName}
|
||||||
|
|
||||||
partial class {className} : RemoteObjectBase, {originalName}
|
|
||||||
{{
|
{{
|
||||||
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(
|
// Add the source code to the compilation.
|
||||||
$"{{ typeof({classSymbol.ToDisplayString()}), typeof({namespaceName}.{className}) }}");
|
context.AddSource($"{className}.g.cs", SourceText.From(code, Encoding.UTF8));
|
||||||
}
|
|
||||||
|
|
||||||
if (methods.Count != 0)
|
frontendContextRepo.Add(
|
||||||
{
|
$"{{ typeof({classSymbol.ToDisplayString()}), typeof({namespaceName}.{className}) }}");
|
||||||
var methodsStringed = methods.Select(i =>
|
}
|
||||||
$"typeof({i.Item1}).GetMethod(\"{i.Item2.Name}\", [{string.Join(", ", i.Item2.Parameters.Select(p => $"typeof({p.Type.ToDisplayString()})"))}])")
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
var coCodegenRepoCode = @$"// <auto-generated/>
|
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 = @$"// <auto-generated/>
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace mROA.Codegen;
|
namespace mROA.Codegen
|
||||||
|
|
||||||
public class CoCodegenMethodRepository : IMethodRepository
|
|
||||||
{{
|
{{
|
||||||
private readonly List<MethodInfo> _methods = [
|
public class CoCodegenMethodRepository : IMethodRepository
|
||||||
{string.Join(", // test comment\r\n\t\t", methodsStringed)}
|
|
||||||
];
|
|
||||||
public MethodInfo GetMethod(int id)
|
|
||||||
{{
|
{{
|
||||||
if (_methods.Count <= id)
|
private readonly List<MethodInfo> _methods = new () {{
|
||||||
return null;
|
{string.Join(",\r\n\t\t\t", methodsStringed)}
|
||||||
|
}};
|
||||||
return _methods[id];
|
|
||||||
}}
|
|
||||||
|
|
||||||
public int RegisterMethod(MethodInfo method)
|
public MethodInfo GetMethod(int id)
|
||||||
{{
|
{{
|
||||||
_methods.Add(method);
|
if (_methods.Count <= id)
|
||||||
return _methods.Count - 1;
|
return null;
|
||||||
}}
|
|
||||||
|
return _methods[id];
|
||||||
|
}}
|
||||||
|
|
||||||
public IEnumerable<MethodInfo> GetMethods()
|
public int RegisterMethod(MethodInfo method)
|
||||||
{{
|
{{
|
||||||
return _methods;
|
_methods.Add(method);
|
||||||
}}
|
return _methods.Count - 1;
|
||||||
|
}}
|
||||||
|
|
||||||
public void Inject<T>(T dependency)
|
public IEnumerable<MethodInfo> GetMethods()
|
||||||
{{
|
{{
|
||||||
|
return _methods;
|
||||||
|
}}
|
||||||
|
|
||||||
|
public void Inject<T>(T dependency)
|
||||||
|
{{
|
||||||
|
}}
|
||||||
}}
|
}}
|
||||||
}}
|
}}
|
||||||
";
|
";
|
||||||
context.AddSource($"CoCodegenMethodRepository.g.cs", SourceText.From(coCodegenRepoCode, Encoding.UTF8));
|
context.AddSource($"CoCodegenMethodRepository.g.cs", SourceText.From(coCodegenRepoCode, Encoding.UTF8));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frontendContextRepo.Count != 0)
|
if (frontendContextRepo.Count != 0)
|
||||||
{
|
{
|
||||||
var fronendRepoCode = @$"// <auto-generated/>
|
var fronendRepoCode = @$"// <auto-generated/>
|
||||||
using System.Collections.Frozen;
|
|
||||||
using mROA.Implementation;
|
using mROA.Implementation;
|
||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
namespace mROA.Codegen;
|
namespace mROA.Codegen
|
||||||
|
|
||||||
public sealed class RemoteTypeBinder
|
|
||||||
{{
|
{{
|
||||||
static RemoteTypeBinder(){{
|
public sealed class RemoteTypeBinder
|
||||||
RemoteContextRepository.RemoteTypes = new Dictionary<Type, Type> {{
|
{{
|
||||||
{string.Join(", \r\n\t\t", frontendContextRepo)}}}.ToFrozenDictionary();
|
static RemoteTypeBinder(){{
|
||||||
|
RemoteContextRepository.RemoteTypes = new Dictionary<Type, Type> {{
|
||||||
|
{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<InterfaceDeclarationSyntax>();
|
||||||
|
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<AttributeListSyntax> 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+62
-58
@@ -1,72 +1,76 @@
|
|||||||
using System.Net;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using mROA.Implementation;
|
using mROA.Implementation;
|
||||||
|
|
||||||
namespace mROA.Test;
|
namespace mROA.Test
|
||||||
|
|
||||||
public class NextGenTest
|
|
||||||
{
|
{
|
||||||
private TcpListener _listener;
|
public class NextGenTest
|
||||||
private NextGenerationInteractionModule _interactionModuleA;
|
|
||||||
private NextGenerationInteractionModule _interactionModuleB;
|
|
||||||
private Guid[] guids = [Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid()];
|
|
||||||
|
|
||||||
[SetUp]
|
|
||||||
public void Setup()
|
|
||||||
{
|
{
|
||||||
_listener = new TcpListener(IPAddress.Loopback, 4567);
|
private TcpListener _listener;
|
||||||
_interactionModuleA = new NextGenerationInteractionModule();
|
private NextGenerationInteractionModule _interactionModuleA;
|
||||||
_interactionModuleA.Inject(new JsonSerializationToolkit());
|
private NextGenerationInteractionModule _interactionModuleB;
|
||||||
_interactionModuleB = new NextGenerationInteractionModule();
|
private Guid[] guids = new[] { Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid() };
|
||||||
_interactionModuleB.Inject(new JsonSerializationToolkit());
|
|
||||||
|
|
||||||
}
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
[Test]
|
|
||||||
public void MultithreadedTest()
|
|
||||||
{
|
|
||||||
|
|
||||||
Task.Run(() =>
|
|
||||||
{
|
{
|
||||||
_listener.Start();
|
_listener = new TcpListener(IPAddress.Loopback, 4567);
|
||||||
_interactionModuleB.BaseStream = _listener.AcceptTcpClient().GetStream();
|
_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]
|
foreach (var guid in guids)
|
||||||
public void TearDown()
|
{
|
||||||
{
|
_interactionModuleB.PostMessage(new NetworkMessage { Id = guid, Data = "Hello user"u8.ToArray() });
|
||||||
_listener.Dispose();
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net9.0</TargetFramework>
|
<TargetFramework>netstandard2.1</TargetFramework>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
namespace mROA.Abstract;
|
using System;
|
||||||
|
|
||||||
public interface ICommandExecution
|
namespace mROA.Abstract
|
||||||
{
|
{
|
||||||
Guid Id { get; init; }
|
public interface ICommandExecution
|
||||||
int ClientId { get; set; }
|
{
|
||||||
int CommandId { get; }
|
Guid Id { get; set; }
|
||||||
|
int ClientId { get; set; }
|
||||||
|
int CommandId { get; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
namespace mROA.Abstract;
|
namespace mROA.Abstract
|
||||||
|
|
||||||
public delegate void ConnectionHandler(IRepresentationModule representationModule);
|
|
||||||
public delegate void DisconnectionHandler(IRepresentationModule representationModule);
|
|
||||||
|
|
||||||
public interface IConnectionHub : IInjectableModule
|
|
||||||
{
|
{
|
||||||
void RegisterInteraction(INextGenerationInteractionModule interaction);
|
public delegate void ConnectionHandler(IRepresentationModule representationModule);
|
||||||
INextGenerationInteractionModule GetInteracion(int id);
|
public delegate void DisconnectionHandler(IRepresentationModule representationModule);
|
||||||
event ConnectionHandler? OnConnected;
|
|
||||||
event DisconnectionHandler? OnDisconnected;
|
public interface IConnectionHub : IInjectableModule
|
||||||
|
{
|
||||||
|
void RegisterInteraction(INextGenerationInteractionModule interaction);
|
||||||
|
INextGenerationInteractionModule GetInteracion(int id);
|
||||||
|
event ConnectionHandler? OnConnected;
|
||||||
|
event DisconnectionHandler? OnDisconnected;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,14 @@
|
|||||||
namespace mROA.Abstract;
|
using System;
|
||||||
|
|
||||||
public interface IContextRepository : IInjectableModule
|
namespace mROA.Abstract
|
||||||
{
|
{
|
||||||
int ResisterObject(object o);
|
public interface IContextRepository : IInjectableModule
|
||||||
void ClearObject(int id);
|
{
|
||||||
object GetObject(int id);
|
int ResisterObject(object o);
|
||||||
T? GetObject<T>(int id);
|
void ClearObject(int id);
|
||||||
object GetSingleObject(Type type);
|
object GetObject(int id);
|
||||||
int GetObjectIndex(object o);
|
T? GetObject<T>(int id);
|
||||||
|
object GetSingleObject(Type type);
|
||||||
|
int GetObjectIndex(object o);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
namespace mROA.Abstract;
|
namespace mROA.Abstract
|
||||||
|
|
||||||
public interface IContextRepositoryHub
|
|
||||||
{
|
{
|
||||||
IContextRepository GetRepository(int clientId);
|
public interface IContextRepositoryHub
|
||||||
|
{
|
||||||
|
IContextRepository GetRepository(int clientId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
using mROA.Implementation;
|
using mROA.Implementation;
|
||||||
|
|
||||||
namespace mROA.Abstract;
|
namespace mROA.Abstract
|
||||||
|
|
||||||
public interface IExecuteModule : IInjectableModule
|
|
||||||
{
|
{
|
||||||
ICommandExecution Execute(ICallRequest command, IContextRepository contextRepository);
|
public interface IExecuteModule : IInjectableModule
|
||||||
|
{
|
||||||
|
ICommandExecution Execute(ICallRequest command, IContextRepository contextRepository);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
namespace mROA.Abstract;
|
namespace mROA.Abstract
|
||||||
|
{
|
||||||
public interface IFrontendBridge : IInjectableModule;
|
public interface IFrontendBridge : IInjectableModule
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
namespace mROA.Abstract;
|
using System;
|
||||||
|
|
||||||
public interface IGatewayModule : IDisposable, IInjectableModule
|
namespace mROA.Abstract
|
||||||
{
|
{
|
||||||
void Run();
|
public interface IGatewayModule : IDisposable, IInjectableModule
|
||||||
|
{
|
||||||
|
void Run();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
namespace mROA.Abstract;
|
namespace mROA.Abstract
|
||||||
|
|
||||||
public interface IIdentityGenerator : IInjectableModule
|
|
||||||
{
|
{
|
||||||
int GetNextIdentity();
|
public interface IIdentityGenerator : IInjectableModule
|
||||||
|
{
|
||||||
|
int GetNextIdentity();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
namespace mROA.Abstract;
|
namespace mROA.Abstract
|
||||||
|
|
||||||
public interface IInjectableModule
|
|
||||||
{
|
{
|
||||||
void Inject<T>(T dependency);
|
public interface IInjectableModule
|
||||||
|
{
|
||||||
|
void Inject<T>(T dependency);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using mROA.Implementation;
|
using mROA.Implementation;
|
||||||
|
|
||||||
namespace mROA.Abstract;
|
namespace mROA.Abstract
|
||||||
|
|
||||||
public interface INextGenerationInteractionModule : IInjectableModule
|
|
||||||
{
|
{
|
||||||
int ConnectionId { get; }
|
public interface INextGenerationInteractionModule : IInjectableModule
|
||||||
public Stream? BaseStream { get; set; }
|
{
|
||||||
Task<NetworkMessage> GetNextMessageReceiving();
|
int ConnectionId { get; }
|
||||||
Task PostMessage(NetworkMessage message);
|
public Stream? BaseStream { get; set; }
|
||||||
void HandleMessage(NetworkMessage message);
|
Task<NetworkMessage> GetNextMessageReceiving();
|
||||||
NetworkMessage[] UnhandledMessages { get; }
|
Task PostMessage(NetworkMessage message);
|
||||||
NetworkMessage? FirstByFilter(Predicate<NetworkMessage> predicate);
|
void HandleMessage(NetworkMessage message);
|
||||||
|
NetworkMessage[] UnhandledMessages { get; }
|
||||||
|
NetworkMessage? FirstByFilter(Predicate<NetworkMessage> predicate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
using System.Reflection;
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
namespace mROA.Abstract;
|
namespace mROA.Abstract
|
||||||
|
|
||||||
public interface IMethodRepository : IInjectableModule
|
|
||||||
{
|
{
|
||||||
MethodInfo GetMethod(int id);
|
public interface IMethodRepository : IInjectableModule
|
||||||
int RegisterMethod(MethodInfo method);
|
{
|
||||||
|
MethodInfo GetMethod(int id);
|
||||||
|
int RegisterMethod(MethodInfo method);
|
||||||
|
|
||||||
IEnumerable<MethodInfo> GetMethods();
|
IEnumerable<MethodInfo> GetMethods();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
namespace mROA.Abstract;
|
namespace mROA.Abstract
|
||||||
|
|
||||||
public interface IOwnershipRepository
|
|
||||||
{
|
{
|
||||||
int GetOwnershipId();
|
public interface IOwnershipRepository
|
||||||
int GetHostOwnershipId();
|
{
|
||||||
|
int GetOwnershipId();
|
||||||
|
int GetHostOwnershipId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
namespace mROA.Abstract;
|
namespace mROA.Abstract
|
||||||
|
|
||||||
public interface IRepresentationModuleProducer : IInjectableModule
|
|
||||||
{
|
{
|
||||||
IRepresentationModule Produce(int id);
|
public interface IRepresentationModuleProducer : IInjectableModule
|
||||||
|
{
|
||||||
|
IRepresentationModule Produce(int id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,31 +1,34 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using mROA.Implementation;
|
using mROA.Implementation;
|
||||||
using mROA.Implementation.CommandExecution;
|
using mROA.Implementation.CommandExecution;
|
||||||
|
|
||||||
namespace mROA.Abstract;
|
namespace mROA.Abstract
|
||||||
|
|
||||||
public interface ISerialisationModule : IInjectableModule
|
|
||||||
{
|
{
|
||||||
void HandleIncomingRequest(int clientId, byte[] message);
|
public interface ISerialisationModule : IInjectableModule
|
||||||
void PostResponse(NetworkMessage message, int clientId);
|
|
||||||
void SendWelcomeMessage(int clientId);
|
|
||||||
public interface IFrontendSerialisationModule : IInjectableModule
|
|
||||||
{
|
{
|
||||||
int ClientId { get; }
|
void HandleIncomingRequest(int clientId, byte[] message);
|
||||||
Task<T> GetNextCommandExecution<T>(Guid requestId) where T : ICommandExecution;
|
void PostResponse(NetworkMessage message, int clientId);
|
||||||
Task<FinalCommandExecution<T>> GetFinalCommandExecution<T>(Guid requestId);
|
void SendWelcomeMessage(int clientId);
|
||||||
void PostCallRequest(ICallRequest callRequest);
|
public interface IFrontendSerialisationModule : IInjectableModule
|
||||||
|
{
|
||||||
|
int ClientId { get; }
|
||||||
|
Task<T> GetNextCommandExecution<T>(Guid requestId) where T : ICommandExecution;
|
||||||
|
Task<FinalCommandExecution<T>> GetFinalCommandExecution<T>(Guid requestId);
|
||||||
|
void PostCallRequest(ICallRequest callRequest);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public interface IRepresentationModule : IInjectableModule
|
public interface IRepresentationModule : IInjectableModule
|
||||||
{
|
{
|
||||||
int Id { get; }
|
int Id { get; }
|
||||||
Task<T> GetMessageAsync<T>(Guid? requestId = null, MessageType? messageType = null);
|
Task<T> GetMessageAsync<T>(Guid? requestId = null, MessageType? messageType = null);
|
||||||
T GetMessage<T>(Guid? requestId = null, MessageType? messageType = null);
|
T GetMessage<T>(Guid? requestId = null, MessageType? messageType = null);
|
||||||
Task<byte[]> GetRawMessage(Guid? requestId = null, MessageType? messageType = null);
|
Task<byte[]> GetRawMessage(Guid? requestId = null, MessageType? messageType = null);
|
||||||
|
|
||||||
Task PostCallMessageAsync<T>(Guid id, MessageType messageType, T payload) where T : notnull;
|
Task PostCallMessageAsync<T>(Guid id, MessageType messageType, T payload) where T : notnull;
|
||||||
Task PostCallMessageAsync(Guid id, MessageType messageType, object payload, Type payloadType);
|
Task PostCallMessageAsync(Guid id, MessageType messageType, object payload, Type payloadType);
|
||||||
void PostCallMessage<T>(Guid id, MessageType messageType, T payload) where T : notnull;
|
void PostCallMessage<T>(Guid id, MessageType messageType, T payload) where T : notnull;
|
||||||
void PostCallMessage(Guid id, MessageType messageType, object payload, Type payloadType);
|
void PostCallMessage(Guid id, MessageType messageType, object payload, Type payloadType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,17 @@
|
|||||||
namespace mROA.Abstract;
|
using System;
|
||||||
|
|
||||||
public interface ISerializationToolkit : IInjectableModule
|
namespace mROA.Abstract
|
||||||
{
|
{
|
||||||
byte[] Serialize<T>(T objectToSerialize);
|
public interface ISerializationToolkit : IInjectableModule
|
||||||
byte[] Serialize(object objectToSerialize, Type type);
|
{
|
||||||
T? Deserialize<T>(byte[] rawData);
|
byte[] Serialize<T>(T objectToSerialize);
|
||||||
object? Deserialize(byte[] rawData, Type type);
|
byte[] Serialize(object objectToSerialize, Type type);
|
||||||
T? Deserialize<T>(Span<byte> rawData);
|
T? Deserialize<T>(byte[] rawData);
|
||||||
object? Deserialize(Span<byte> rawData, Type type);
|
object? Deserialize(byte[] rawData, Type type);
|
||||||
T Cast<T>(object nonCasted);
|
T? Deserialize<T>(Span<byte> rawData);
|
||||||
object Cast(object nonCasted, Type type);
|
object? Deserialize(Span<byte> rawData, Type type);
|
||||||
|
T Cast<T>(object nonCasted);
|
||||||
|
object Cast(object nonCasted, Type type);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
namespace mROA.Implementation.Attributes;
|
using System;
|
||||||
|
|
||||||
public class SharedObjectInterfaceAttribute : Attribute;
|
namespace mROA.Implementation.Attributes
|
||||||
|
{
|
||||||
|
public class SharedObjectInterfaceAttribute : Attribute { }
|
||||||
|
}
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
namespace mROA.Implementation.Attributes;
|
using System;
|
||||||
|
|
||||||
public class SharedObjectSingletonAttribute : Attribute;
|
namespace mROA.Implementation.Attributes
|
||||||
|
{
|
||||||
|
public class SharedObjectSingletonAttribute : Attribute { }
|
||||||
|
}
|
||||||
@@ -1,17 +1,18 @@
|
|||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
|
|
||||||
namespace mROA.Implementation.Backend;
|
namespace mROA.Implementation.Backend
|
||||||
|
|
||||||
public class BackendIdentityGenerator : IIdentityGenerator
|
|
||||||
{
|
{
|
||||||
private int _currentId;
|
public class BackendIdentityGenerator : IIdentityGenerator
|
||||||
|
|
||||||
public int GetNextIdentity()
|
|
||||||
{
|
|
||||||
return ++_currentId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Inject<T>(T dependency)
|
|
||||||
{
|
{
|
||||||
|
private int _currentId;
|
||||||
|
|
||||||
|
public int GetNextIdentity()
|
||||||
|
{
|
||||||
|
return ++_currentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Inject<T>(T dependency)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,37 +1,39 @@
|
|||||||
|
using System;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
using mROA.Implementation.Bootstrap;
|
using mROA.Implementation.Bootstrap;
|
||||||
|
|
||||||
namespace mROA.Implementation.Backend;
|
namespace mROA.Implementation.Backend
|
||||||
|
|
||||||
public static class BasicConfigurationExtensions
|
|
||||||
{
|
{
|
||||||
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)
|
public static void UseNetworkGateway(this FullMixBuilder builder, IPEndPoint endPoint, Type interactionModuleType, params IInjectableModule[] injectableModules)
|
||||||
{
|
{
|
||||||
builder.Modules.Add(new NetworkGatewayModule(endPoint, interactionModuleType, injectableModules));
|
builder.Modules.Add(new NetworkGatewayModule(endPoint, interactionModuleType, injectableModules));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void UseBasicExecution(this FullMixBuilder builder)
|
public static void UseBasicExecution(this FullMixBuilder builder)
|
||||||
{
|
{
|
||||||
builder.Modules.Add(new BasicExecutionModule());
|
builder.Modules.Add(new BasicExecutionModule());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void UseCollectableContextRepository(this FullMixBuilder builder, params Assembly[] assemblies)
|
public static void UseCollectableContextRepository(this FullMixBuilder builder, params Assembly[] assemblies)
|
||||||
{
|
{
|
||||||
var repo = new ContextRepository();
|
var repo = new ContextRepository();
|
||||||
repo.FillSingletons(assemblies);
|
repo.FillSingletons(assemblies);
|
||||||
TransmissionConfig.RealContextRepository = repo;
|
TransmissionConfig.RealContextRepository = repo;
|
||||||
builder.Modules.Add(repo);
|
builder.Modules.Add(repo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SetupMethodsRepository(this FullMixBuilder builder, IMethodRepository methodRepository)
|
public static void SetupMethodsRepository(this FullMixBuilder builder, IMethodRepository methodRepository)
|
||||||
{
|
{
|
||||||
builder.Modules.Add(methodRepository);
|
builder.Modules.Add(methodRepository);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,121 +1,128 @@
|
|||||||
using System.Reflection;
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
using mROA.Implementation.CommandExecution;
|
using mROA.Implementation.CommandExecution;
|
||||||
|
|
||||||
namespace mROA.Implementation.Backend;
|
namespace mROA.Implementation.Backend
|
||||||
|
|
||||||
public class BasicExecutionModule : IExecuteModule
|
|
||||||
{
|
{
|
||||||
private IMethodRepository? _methodRepo;
|
public class BasicExecutionModule : IExecuteModule
|
||||||
|
|
||||||
public void Inject<T>(T dependency)
|
|
||||||
{
|
{
|
||||||
if (dependency is IMethodRepository methodRepo) _methodRepo = methodRepo;
|
private IMethodRepository? _methodRepo;
|
||||||
}
|
|
||||||
|
|
||||||
public ICommandExecution Execute(ICallRequest command, IContextRepository contextRepository)
|
public void Inject<T>(T dependency)
|
||||||
{
|
{
|
||||||
if (_methodRepo is null)
|
if (dependency is IMethodRepository methodRepo) _methodRepo = methodRepo;
|
||||||
throw new NullReferenceException("Method repository was not defined");
|
}
|
||||||
|
|
||||||
|
public ICommandExecution Execute(ICallRequest command, IContextRepository contextRepository)
|
||||||
|
{
|
||||||
|
if (_methodRepo is null)
|
||||||
|
throw new NullReferenceException("Method repository was not defined");
|
||||||
|
|
||||||
if (contextRepository is null)
|
if (contextRepository is null)
|
||||||
throw new NullReferenceException("Context repository was not defined");
|
throw new NullReferenceException("Context repository was not defined");
|
||||||
|
|
||||||
var currentCommand = _methodRepo.GetMethod(command.CommandId);
|
var currentCommand = _methodRepo.GetMethod(command.CommandId);
|
||||||
if (currentCommand == null)
|
if (currentCommand == null)
|
||||||
throw new Exception($"Command {command.CommandId} not found");
|
throw new Exception($"Command {command.CommandId} not found");
|
||||||
|
|
||||||
var context = command.ObjectId != -1
|
var context = command.ObjectId != -1
|
||||||
? contextRepository.GetObject(command.ObjectId)
|
? contextRepository.GetObject(command.ObjectId)
|
||||||
: contextRepository.GetSingleObject(currentCommand.DeclaringType!);
|
: contextRepository.GetSingleObject(currentCommand.DeclaringType!);
|
||||||
var parameter = command.Parameter;
|
var parameter = command.Parameter;
|
||||||
|
|
||||||
if (currentCommand.ReturnType.BaseType == typeof(Task) &&
|
if (currentCommand.ReturnType.BaseType == typeof(Task) &&
|
||||||
currentCommand.ReturnType.GenericTypeArguments.Length == 1)
|
currentCommand.ReturnType.GenericTypeArguments.Length == 1)
|
||||||
return TypedExecuteAsync(currentCommand, context, parameter, command);
|
return TypedExecuteAsync(currentCommand, context, parameter, command);
|
||||||
|
|
||||||
if (currentCommand.ReturnType == typeof(Task))
|
if (currentCommand.ReturnType == typeof(Task))
|
||||||
return ExecuteAsync(currentCommand, context, parameter, command);
|
return ExecuteAsync(currentCommand, context, parameter, command);
|
||||||
|
|
||||||
return Execute(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
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
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,
|
var finalResult = currentCommand.Invoke(context, parameter is null ? new object[0] : new[]
|
||||||
Exception = e.ToString()
|
{ parameter });
|
||||||
};
|
return new TypedFinalCommandExecution
|
||||||
}
|
{
|
||||||
}
|
CommandId = command.CommandId, Result = finalResult,
|
||||||
|
Id = command.Id,
|
||||||
private static ICommandExecution ExecuteAsync(MethodInfo currentCommand, object context, object? parameter,
|
Type = currentCommand.ReturnType
|
||||||
ICallRequest command)
|
};
|
||||||
{
|
}
|
||||||
var tokenSource = new CancellationTokenSource();
|
catch (Exception e)
|
||||||
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
|
|
||||||
{
|
{
|
||||||
Id = command.Id, CommandId = command.CommandId,
|
return new ExceptionCommandExecution
|
||||||
Exception = e.ToString()
|
{
|
||||||
};
|
Id = command.Id, CommandId = command.CommandId,
|
||||||
|
Exception = e.ToString()
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static ICommandExecution TypedExecuteAsync(MethodInfo currentCommand, object context, object? parameter,
|
private static ICommandExecution ExecuteAsync(MethodInfo currentCommand, object context, object? parameter,
|
||||||
ICallRequest command)
|
ICallRequest command)
|
||||||
{
|
|
||||||
var tokenSource = new CancellationTokenSource();
|
|
||||||
var token = tokenSource.Token;
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
var result =
|
var tokenSource = new CancellationTokenSource();
|
||||||
(Task)currentCommand.Invoke(context, parameter is null ? [token] : [parameter, token])!;
|
var token = tokenSource.Token;
|
||||||
|
try
|
||||||
result.Wait(token);
|
|
||||||
|
|
||||||
var finalResult = result.GetType().GetProperty("Result")?.GetValue(result);
|
|
||||||
return new TypedFinalCommandExecution
|
|
||||||
{
|
{
|
||||||
Id = command.Id,
|
var result = (Task)currentCommand.Invoke(context, parameter is null ? new object[] { token } : new[]
|
||||||
Result = finalResult,
|
{ parameter, token })!;
|
||||||
CommandId = command.CommandId,
|
|
||||||
Type = finalResult?.GetType()
|
|
||||||
};
|
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,
|
var result =
|
||||||
Exception = e.ToString()
|
(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()
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,35 +1,38 @@
|
|||||||
using mROA.Abstract;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using mROA.Abstract;
|
||||||
|
|
||||||
namespace mROA.Implementation.Backend;
|
namespace mROA.Implementation.Backend
|
||||||
|
|
||||||
public class ConnectionHub : IConnectionHub
|
|
||||||
{
|
{
|
||||||
private readonly Dictionary<int, INextGenerationInteractionModule> _connections = new();
|
public class ConnectionHub : IConnectionHub
|
||||||
private ISerializationToolkit? _serializationToolkit;
|
{
|
||||||
|
private readonly Dictionary<int, INextGenerationInteractionModule> _connections = new();
|
||||||
|
private ISerializationToolkit? _serializationToolkit;
|
||||||
|
|
||||||
public void RegisterInteraction(INextGenerationInteractionModule interaction)
|
public void RegisterInteraction(INextGenerationInteractionModule interaction)
|
||||||
{
|
{
|
||||||
if (_serializationToolkit is null)
|
if (_serializationToolkit is null)
|
||||||
throw new NullReferenceException("Serialization toolkit is null");
|
throw new NullReferenceException("Serialization toolkit is null");
|
||||||
|
|
||||||
_connections.Add(interaction.ConnectionId, interaction);
|
_connections.Add(interaction.ConnectionId, interaction);
|
||||||
var module = new RepresentationModule();
|
var module = new RepresentationModule();
|
||||||
module.Inject(_serializationToolkit);
|
module.Inject(_serializationToolkit);
|
||||||
module.Inject(interaction);
|
module.Inject(interaction);
|
||||||
OnConnected?.Invoke(module);
|
OnConnected?.Invoke(module);
|
||||||
}
|
}
|
||||||
|
|
||||||
public INextGenerationInteractionModule GetInteracion(int id)
|
public INextGenerationInteractionModule GetInteracion(int id)
|
||||||
{
|
{
|
||||||
return _connections!.GetValueOrDefault(id, null) ?? throw new Exception("No connection found");
|
return _connections!.GetValueOrDefault(id, null) ?? throw new Exception("No connection found");
|
||||||
}
|
}
|
||||||
|
|
||||||
public event ConnectionHandler? OnConnected;
|
public event ConnectionHandler? OnConnected;
|
||||||
public event DisconnectionHandler? OnDisconnected;
|
public event DisconnectionHandler? OnDisconnected;
|
||||||
public void Inject<T>(T dependency)
|
public void Inject<T>(T dependency)
|
||||||
{
|
{
|
||||||
if (dependency is ISerializationToolkit serializationToolkit)
|
if (dependency is ISerializationToolkit serializationToolkit)
|
||||||
_serializationToolkit = serializationToolkit;
|
_serializationToolkit = serializationToolkit;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,88 +1,92 @@
|
|||||||
using System.Collections.Frozen;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
using mROA.Implementation.Attributes;
|
using mROA.Implementation.Attributes;
|
||||||
|
|
||||||
namespace mROA.Implementation.Backend;
|
namespace mROA.Implementation.Backend
|
||||||
|
|
||||||
public class ContextRepository : IContextRepository
|
|
||||||
{
|
{
|
||||||
private FrozenDictionary<int, object?>? _singletons;
|
public class ContextRepository : IContextRepository
|
||||||
private object?[] _storage = new object[StartupSize];
|
|
||||||
|
|
||||||
private Task<int> _lastIndexFinder = Task.FromResult(0);
|
|
||||||
|
|
||||||
private const int StartupSize = 1024;
|
|
||||||
private const int GrowSize = 128;
|
|
||||||
|
|
||||||
|
|
||||||
public void FillSingletons(params Assembly[] assembly)
|
|
||||||
{
|
{
|
||||||
var types = assembly.SelectMany(x => x.GetTypes()).Where(type =>
|
private Dictionary<int, object?>? _singletons;
|
||||||
type is { IsClass: true, IsAbstract: false, IsGenericType: false } &&
|
private object?[] _storage = new object[StartupSize];
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int ResisterObject(object o)
|
private Task<int> _lastIndexFinder = Task.FromResult(0);
|
||||||
{
|
|
||||||
if (!_lastIndexFinder.IsCompleted)
|
|
||||||
_lastIndexFinder.Wait();
|
|
||||||
|
|
||||||
_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 FillSingletons(params Assembly[] assembly)
|
||||||
}
|
|
||||||
|
|
||||||
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<T>(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)
|
var types = assembly.SelectMany(x => x.GetTypes()).Where(type =>
|
||||||
return i;
|
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];
|
public int ResisterObject(object o)
|
||||||
Array.Copy(_storage, nextStorage, _storage.Length);
|
{
|
||||||
_storage = nextStorage;
|
if (!_lastIndexFinder.IsCompleted)
|
||||||
return _storage.Length;
|
_lastIndexFinder.Wait();
|
||||||
}
|
|
||||||
public void Inject<T>(T dependency)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
_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<T>(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>(T dependency)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,50 +1,58 @@
|
|||||||
|
using System;
|
||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
|
|
||||||
namespace mROA.Implementation.Backend;
|
namespace mROA.Implementation.Backend
|
||||||
|
|
||||||
public class HubRequestExtractor(Type extractoType) : IInjectableModule
|
|
||||||
{
|
{
|
||||||
private IConnectionHub? _hub;
|
public class HubRequestExtractor : IInjectableModule
|
||||||
|
|
||||||
private IContextRepository? _contextRepository;
|
|
||||||
private IMethodRepository? _methodRepository;
|
|
||||||
private ISerializationToolkit? _serializationToolkit;
|
|
||||||
private IExecuteModule? _executeModule;
|
|
||||||
|
|
||||||
public void Inject<T>(T dependency)
|
|
||||||
{
|
{
|
||||||
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:
|
_extractorType = extractorType;
|
||||||
_hub = connectionHub;
|
}
|
||||||
_hub.OnConnected += HubOnOnConnected;
|
|
||||||
break;
|
public void Inject<T>(T dependency)
|
||||||
case IContextRepository contextRepository:
|
{
|
||||||
_contextRepository = contextRepository;
|
switch (dependency)
|
||||||
break;
|
{
|
||||||
case IMethodRepository methodRepository:
|
case IConnectionHub connectionHub:
|
||||||
_methodRepository = methodRepository;
|
_hub = connectionHub;
|
||||||
break;
|
_hub.OnConnected += HubOnOnConnected;
|
||||||
case ISerializationToolkit serializationToolkit:
|
break;
|
||||||
_serializationToolkit = serializationToolkit;
|
case IContextRepository contextRepository:
|
||||||
break;
|
_contextRepository = contextRepository;
|
||||||
case IExecuteModule executeModule:
|
break;
|
||||||
_executeModule = executeModule;
|
case IMethodRepository methodRepository:
|
||||||
break;
|
_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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,56 +1,65 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
|
|
||||||
namespace mROA.Implementation.Backend;
|
namespace mROA.Implementation.Backend
|
||||||
|
|
||||||
public class MultiClientContextRepository(Func<int, IContextRepository> produceRepository) : IContextRepository, IContextRepositoryHub
|
|
||||||
{
|
{
|
||||||
private Dictionary<int, IContextRepository> _repositories = new();
|
public class MultiClientContextRepository : IContextRepository, IContextRepositoryHub
|
||||||
|
|
||||||
private IContextRepository GetRepositoryByClientId(int clientId)
|
|
||||||
{
|
{
|
||||||
if (_repositories.TryGetValue(clientId, out var repository))
|
private Dictionary<int, IContextRepository> _repositories = new();
|
||||||
return repository;
|
private readonly Func<int, IContextRepository> _produceRepository;
|
||||||
|
|
||||||
|
public MultiClientContextRepository(Func<int, IContextRepository> produceRepository)
|
||||||
|
{
|
||||||
|
_produceRepository = produceRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IContextRepository GetRepositoryByClientId(int clientId)
|
||||||
|
{
|
||||||
|
if (_repositories.TryGetValue(clientId, out var repository))
|
||||||
|
return repository;
|
||||||
|
|
||||||
var created = produceRepository(clientId);
|
var created = _produceRepository(clientId);
|
||||||
_repositories.Add(clientId, created);
|
_repositories.Add(clientId, created);
|
||||||
return created;
|
return created;
|
||||||
}
|
}
|
||||||
public void Inject<T>(T dependency)
|
public void Inject<T>(T dependency)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public int ResisterObject(object o)
|
public int ResisterObject(object o)
|
||||||
{
|
{
|
||||||
return GetRepositoryByClientId(TransmissionConfig.OwnershipRepository.GetOwnershipId()).ResisterObject(o);
|
return GetRepositoryByClientId(TransmissionConfig.OwnershipRepository.GetOwnershipId()).ResisterObject(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClearObject(int id)
|
public void ClearObject(int id)
|
||||||
{
|
{
|
||||||
GetRepositoryByClientId(TransmissionConfig.OwnershipRepository.GetOwnershipId()).ClearObject(id);
|
GetRepositoryByClientId(TransmissionConfig.OwnershipRepository.GetOwnershipId()).ClearObject(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object GetObject(int id)
|
public object GetObject(int id)
|
||||||
{
|
{
|
||||||
return GetRepositoryByClientId(TransmissionConfig.OwnershipRepository.GetOwnershipId()).GetObject(id);
|
return GetRepositoryByClientId(TransmissionConfig.OwnershipRepository.GetOwnershipId()).GetObject(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public T? GetObject<T>(int id)
|
public T? GetObject<T>(int id)
|
||||||
{
|
{
|
||||||
return GetRepositoryByClientId(TransmissionConfig.OwnershipRepository.GetOwnershipId()).GetObject<T>(id);
|
return GetRepositoryByClientId(TransmissionConfig.OwnershipRepository.GetOwnershipId()).GetObject<T>(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object GetSingleObject(Type type)
|
public object GetSingleObject(Type type)
|
||||||
{
|
{
|
||||||
return GetRepositoryByClientId(TransmissionConfig.OwnershipRepository.GetOwnershipId()).GetSingleObject(type);
|
return GetRepositoryByClientId(TransmissionConfig.OwnershipRepository.GetOwnershipId()).GetSingleObject(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetObjectIndex(object o)
|
public int GetObjectIndex(object o)
|
||||||
{
|
{
|
||||||
return GetRepositoryByClientId(TransmissionConfig.OwnershipRepository.GetOwnershipId()).GetObjectIndex(o);
|
return GetRepositoryByClientId(TransmissionConfig.OwnershipRepository.GetOwnershipId()).GetObjectIndex(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IContextRepository GetRepository(int clientId)
|
public IContextRepository GetRepository(int clientId)
|
||||||
{
|
{
|
||||||
return GetRepositoryByClientId(clientId);
|
return GetRepositoryByClientId(clientId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,28 +1,31 @@
|
|||||||
using mROA.Abstract;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using mROA.Abstract;
|
||||||
|
|
||||||
namespace mROA.Implementation.Backend;
|
namespace mROA.Implementation.Backend
|
||||||
|
|
||||||
public class MultiClientOwnershipRepository : IOwnershipRepository
|
|
||||||
{
|
{
|
||||||
private Dictionary<int, int> _ownerships = new();
|
public class MultiClientOwnershipRepository : IOwnershipRepository
|
||||||
|
|
||||||
public int GetOwnershipId()
|
|
||||||
{
|
{
|
||||||
return _ownerships.GetValueOrDefault(Environment.CurrentManagedThreadId, 0);
|
private Dictionary<int, int> _ownerships = new();
|
||||||
}
|
|
||||||
|
|
||||||
public int GetHostOwnershipId()
|
public int GetOwnershipId()
|
||||||
{
|
{
|
||||||
return 0;
|
return _ownerships.GetValueOrDefault(Environment.CurrentManagedThreadId, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RegisterOwnership(int ownershipId)
|
public int GetHostOwnershipId()
|
||||||
{
|
{
|
||||||
_ownerships.TryAdd(Environment.CurrentManagedThreadId, ownershipId);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FreeOwnership()
|
public void RegisterOwnership(int ownershipId)
|
||||||
{
|
{
|
||||||
_ownerships.Remove(Environment.CurrentManagedThreadId);
|
_ownerships.TryAdd(Environment.CurrentManagedThreadId, ownershipId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FreeOwnership()
|
||||||
|
{
|
||||||
|
_ownerships.Remove(Environment.CurrentManagedThreadId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,89 +1,91 @@
|
|||||||
using System.Net;
|
using System;
|
||||||
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
|
|
||||||
namespace mROA.Implementation.Backend;
|
namespace mROA.Implementation.Backend
|
||||||
|
|
||||||
public class NetworkGatewayModule : IGatewayModule
|
|
||||||
{
|
{
|
||||||
private readonly Type? _interactionModuleType;
|
public class NetworkGatewayModule : IGatewayModule
|
||||||
private readonly IInjectableModule[]? _injectableModules;
|
|
||||||
private readonly TcpListener _tcpListener;
|
|
||||||
private IConnectionHub? _hub;
|
|
||||||
private ISerializationToolkit? _serialization;
|
|
||||||
|
|
||||||
public NetworkGatewayModule(IPEndPoint endpoint, Type interactionModuleType, IInjectableModule[] injectableModules)
|
|
||||||
{
|
{
|
||||||
_tcpListener = new(endpoint);
|
private readonly Type? _interactionModuleType;
|
||||||
_interactionModuleType = interactionModuleType;
|
private readonly IInjectableModule[]? _injectableModules;
|
||||||
_injectableModules = injectableModules;
|
private readonly TcpListener _tcpListener;
|
||||||
}
|
private IConnectionHub? _hub;
|
||||||
|
private ISerializationToolkit? _serialization;
|
||||||
|
|
||||||
public void Run()
|
public NetworkGatewayModule(IPEndPoint endpoint, Type interactionModuleType, IInjectableModule[] injectableModules)
|
||||||
{
|
|
||||||
_tcpListener.Start();
|
|
||||||
Console.WriteLine($"Listening on {_tcpListener.LocalEndpoint}");
|
|
||||||
Console.WriteLine("Enter Backspace to stop");
|
|
||||||
|
|
||||||
Task.Run(HandleIncomingConnections);
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
{
|
||||||
var key = Console.ReadKey();
|
_tcpListener = new(endpoint);
|
||||||
if (key.Key == ConsoleKey.Backspace)
|
_interactionModuleType = interactionModuleType;
|
||||||
break;
|
_injectableModules = injectableModules;
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine("Stopping");
|
public void Run()
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
var client = _tcpListener.AcceptTcpClient();
|
_tcpListener.Start();
|
||||||
Console.WriteLine($"Client connected from {client.Client.RemoteEndPoint}");
|
Console.WriteLine($"Listening on {_tcpListener.LocalEndpoint}");
|
||||||
var interaction = Activator.CreateInstance(_interactionModuleType) as INextGenerationInteractionModule;
|
Console.WriteLine("Enter Backspace to stop");
|
||||||
|
|
||||||
foreach (var injectableModule in _injectableModules)
|
Task.Run(HandleIncomingConnections);
|
||||||
interaction!.Inject(injectableModule);
|
|
||||||
|
|
||||||
interaction!.Inject(_serialization);
|
while (true)
|
||||||
|
|
||||||
interaction.BaseStream = client.GetStream();
|
|
||||||
|
|
||||||
interaction.PostMessage(new NetworkMessage
|
|
||||||
{
|
{
|
||||||
Id = Guid.NewGuid(), SchemaId = MessageType.IdAssigning,
|
var key = Console.ReadKey();
|
||||||
Data = _serialization.Serialize(new IdAssingnment { Id = interaction.ConnectionId })
|
if (key.Key == ConsoleKey.Backspace)
|
||||||
});
|
break;
|
||||||
_hub.RegisterInteraction(interaction);
|
}
|
||||||
Console.WriteLine("Client registered");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Inject<T>(T dependency)
|
Console.WriteLine("Stopping");
|
||||||
{
|
}
|
||||||
if (dependency is IConnectionHub interactionModule)
|
|
||||||
_hub = interactionModule;
|
public void Dispose()
|
||||||
if (dependency is ISerializationToolkit serializationToolkit)
|
{
|
||||||
_serialization = serializationToolkit;
|
_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>(T dependency)
|
||||||
|
{
|
||||||
|
if (dependency is IConnectionHub interactionModule)
|
||||||
|
_hub = interactionModule;
|
||||||
|
if (dependency is ISerializationToolkit serializationToolkit)
|
||||||
|
_serialization = serializationToolkit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,20 +1,23 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
|
|
||||||
namespace mROA.Implementation.Bootstrap;
|
namespace mROA.Implementation.Bootstrap
|
||||||
|
|
||||||
public class FullMixBuilder
|
|
||||||
{
|
{
|
||||||
public List<IInjectableModule> Modules { get; } = [];
|
public class FullMixBuilder
|
||||||
|
|
||||||
public void Build()
|
|
||||||
{
|
{
|
||||||
foreach (var module in Modules)
|
public List<IInjectableModule> Modules { get; } = new() { };
|
||||||
foreach (var injection in Modules)
|
|
||||||
module.Inject(injection);
|
|
||||||
}
|
|
||||||
|
|
||||||
public T? GetModule<T>()
|
public void Build()
|
||||||
{
|
{
|
||||||
return Modules.OfType<T>().FirstOrDefault();
|
foreach (var module in Modules)
|
||||||
|
foreach (var injection in Modules)
|
||||||
|
module.Inject(injection);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T? GetModule<T>()
|
||||||
|
{
|
||||||
|
return Modules.OfType<T>().FirstOrDefault();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,24 +1,26 @@
|
|||||||
using System.Text.Json.Serialization;
|
using System;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
|
// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
|
||||||
|
|
||||||
namespace mROA.Implementation;
|
namespace mROA.Implementation
|
||||||
|
|
||||||
public interface ICallRequest
|
|
||||||
{
|
{
|
||||||
Guid Id { get; }
|
public interface ICallRequest
|
||||||
int CommandId { get; }
|
{
|
||||||
int ObjectId { get; }
|
Guid Id { get; }
|
||||||
object? Parameter { get; }
|
int CommandId { get; }
|
||||||
}
|
int ObjectId { get; }
|
||||||
|
object? Parameter { get; }
|
||||||
|
}
|
||||||
|
|
||||||
public class DefaultCallRequest : ICallRequest
|
public class DefaultCallRequest : ICallRequest
|
||||||
{
|
{
|
||||||
public Guid Id { get; set; } = Guid.NewGuid();
|
public Guid Id { get; set; } = Guid.NewGuid();
|
||||||
public int CommandId { get; init; }
|
public int CommandId { get; set; }
|
||||||
public int ObjectId { get; init; } = -1;
|
public int ObjectId { get; set; } = -1;
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public Type? ParameterType { get; init; }
|
public Type? ParameterType { get; set; }
|
||||||
public object? Parameter { get; set; }
|
public object? Parameter { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,17 +1,19 @@
|
|||||||
using mROA.Abstract;
|
using System;
|
||||||
|
using mROA.Abstract;
|
||||||
using mROA.Implementation.Frontend;
|
using mROA.Implementation.Frontend;
|
||||||
|
|
||||||
namespace mROA.Implementation.CommandExecution;
|
namespace mROA.Implementation.CommandExecution
|
||||||
|
|
||||||
public class ExceptionCommandExecution : ICommandExecution
|
|
||||||
{
|
{
|
||||||
public Guid Id { get; init; }
|
public class ExceptionCommandExecution : ICommandExecution
|
||||||
public int ClientId { get; set; }
|
|
||||||
public int CommandId { get; init; }
|
|
||||||
public required string Exception { get; set; }
|
|
||||||
|
|
||||||
public RemoteException GetException()
|
|
||||||
{
|
{
|
||||||
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 };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,20 +1,22 @@
|
|||||||
using System.Text.Json.Serialization;
|
using System;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
|
|
||||||
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
|
||||||
namespace mROA.Implementation.CommandExecution;
|
namespace mROA.Implementation.CommandExecution
|
||||||
|
|
||||||
public class FinalCommandExecution : ICommandExecution
|
|
||||||
{
|
{
|
||||||
public Guid Id { get; init; }
|
public class FinalCommandExecution : ICommandExecution
|
||||||
[JsonIgnore]
|
{
|
||||||
public int ClientId { get; set; }
|
public Guid Id { get; set; }
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public int CommandId { get; init; }
|
public int ClientId { get; set; }
|
||||||
}
|
[JsonIgnore]
|
||||||
|
public int CommandId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public class FinalCommandExecution<T> : FinalCommandExecution
|
public class FinalCommandExecution<T> : FinalCommandExecution
|
||||||
{
|
{
|
||||||
public T? Result { get; init; }
|
public T? Result { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
using System.Text.Json.Serialization;
|
using System;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace mROA.Implementation.CommandExecution;
|
namespace mROA.Implementation.CommandExecution
|
||||||
|
|
||||||
public class TypedFinalCommandExecution : FinalCommandExecution<object>
|
|
||||||
{
|
{
|
||||||
[JsonIgnore]
|
public class TypedFinalCommandExecution : FinalCommandExecution<object>
|
||||||
// ReSharper disable once UnusedAutoPropertyAccessor.Global
|
{
|
||||||
public Type? Type { get; set; }
|
[JsonIgnore]
|
||||||
|
// ReSharper disable once UnusedAutoPropertyAccessor.Global
|
||||||
|
public Type? Type { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,40 +1,42 @@
|
|||||||
using mROA.Abstract;
|
using System;
|
||||||
|
using mROA.Abstract;
|
||||||
|
|
||||||
namespace mROA.Implementation;
|
namespace mROA.Implementation
|
||||||
|
|
||||||
public class CreativeRepresentationModuleProducer : IRepresentationModuleProducer
|
|
||||||
{
|
{
|
||||||
private Type _reprModuleType;
|
public class CreativeRepresentationModuleProducer : IRepresentationModuleProducer
|
||||||
private IInjectableModule[] _creationModules;
|
|
||||||
private IConnectionHub? _hub;
|
|
||||||
|
|
||||||
public CreativeRepresentationModuleProducer(IInjectableModule[] creationModules, Type reprModuleType)
|
|
||||||
{
|
{
|
||||||
_creationModules = creationModules;
|
private Type _reprModuleType;
|
||||||
_reprModuleType = reprModuleType;
|
private IInjectableModule[] _creationModules;
|
||||||
}
|
private IConnectionHub? _hub;
|
||||||
|
|
||||||
|
public CreativeRepresentationModuleProducer(IInjectableModule[] creationModules, Type reprModuleType)
|
||||||
|
{
|
||||||
|
_creationModules = creationModules;
|
||||||
|
_reprModuleType = reprModuleType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void Inject<T>(T dependency)
|
public void Inject<T>(T dependency)
|
||||||
{
|
{
|
||||||
if (dependency is IConnectionHub interactionModule)
|
if (dependency is IConnectionHub interactionModule)
|
||||||
_hub = interactionModule;
|
_hub = interactionModule;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IRepresentationModule Produce(int id)
|
public IRepresentationModule Produce(int id)
|
||||||
{
|
{
|
||||||
if (_hub == null)
|
if (_hub == null)
|
||||||
throw new NullReferenceException("Interaction module is null");
|
throw new NullReferenceException("Interaction module is null");
|
||||||
|
|
||||||
var produced =
|
var produced =
|
||||||
Activator.CreateInstance(_reprModuleType) as IRepresentationModule ??
|
Activator.CreateInstance(_reprModuleType) as IRepresentationModule ??
|
||||||
throw new Exception("Bad serialization module type");
|
throw new Exception("Bad serialization module type");
|
||||||
|
|
||||||
foreach (var creationModule in _creationModules)
|
foreach (var creationModule in _creationModules)
|
||||||
produced.Inject(creationModule);
|
produced.Inject(creationModule);
|
||||||
|
|
||||||
produced.Inject(_hub.GetInteracion(id));
|
produced.Inject(_hub.GetInteracion(id));
|
||||||
|
|
||||||
return produced;
|
return produced;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
namespace mROA.Implementation.Frontend;
|
using System;
|
||||||
|
|
||||||
// public class JsonFrontendSerialisationModule
|
namespace mROA.Implementation.Frontend
|
||||||
|
{
|
||||||
|
// public class JsonFrontendSerialisationModule
|
||||||
// : ISerialisationModule.IFrontendSerialisationModule
|
// : ISerialisationModule.IFrontendSerialisationModule
|
||||||
// {
|
// {
|
||||||
// private IInteractionModule.IFrontendInteractionModule? _interactionModule;
|
// private IInteractionModule.IFrontendInteractionModule? _interactionModule;
|
||||||
@@ -77,8 +79,16 @@ namespace mROA.Implementation.Frontend;
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
public class RemoteException(string error) : Exception
|
public class RemoteException : Exception
|
||||||
{
|
{
|
||||||
public Guid CallRequestId;
|
public Guid CallRequestId;
|
||||||
public override string Message => $"Error in request {CallRequestId} : {error}";
|
private readonly string _error;
|
||||||
|
|
||||||
|
public RemoteException(string error)
|
||||||
|
{
|
||||||
|
_error = error;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Message => $"Error in request {CallRequestId} : {_error}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,43 +1,51 @@
|
|||||||
|
using System;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
|
|
||||||
namespace mROA.Implementation.Frontend;
|
namespace mROA.Implementation.Frontend
|
||||||
|
|
||||||
public class NetworkFrontendBridge(IPEndPoint ipEndPoint) : IFrontendBridge
|
|
||||||
{
|
{
|
||||||
private readonly TcpClient _tcpClient = new();
|
public class NetworkFrontendBridge : IFrontendBridge
|
||||||
private NextGenerationInteractionModule? _interactionModule;
|
|
||||||
private ISerializationToolkit? _serialization;
|
|
||||||
|
|
||||||
public void Inject<T>(T dependency)
|
|
||||||
{
|
{
|
||||||
switch (dependency)
|
private readonly TcpClient _tcpClient = new();
|
||||||
|
private NextGenerationInteractionModule? _interactionModule;
|
||||||
|
private ISerializationToolkit? _serialization;
|
||||||
|
private readonly IPEndPoint _ipEndPoint;
|
||||||
|
|
||||||
|
public NetworkFrontendBridge(IPEndPoint ipEndPoint)
|
||||||
{
|
{
|
||||||
case NextGenerationInteractionModule interactionModule:
|
_ipEndPoint = ipEndPoint;
|
||||||
_interactionModule = interactionModule;
|
|
||||||
break;
|
|
||||||
case ISerializationToolkit toolkit:
|
|
||||||
_serialization = toolkit;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void Connect()
|
public void Inject<T>(T dependency)
|
||||||
{
|
{
|
||||||
if (_interactionModule is null)
|
switch (dependency)
|
||||||
throw new Exception("Interaction module was not injected");
|
{
|
||||||
if (_serialization == null)
|
case NextGenerationInteractionModule interactionModule:
|
||||||
throw new NullReferenceException("Serialization toolkit is not initialized");
|
_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);
|
_tcpClient.Connect(_ipEndPoint);
|
||||||
_interactionModule.BaseStream = _tcpClient.GetStream();
|
_interactionModule.BaseStream = _tcpClient.GetStream();
|
||||||
var welcomeMessage = _interactionModule.GetNextMessageReceiving().GetAwaiter().GetResult();
|
var welcomeMessage = _interactionModule.GetNextMessageReceiving().GetAwaiter().GetResult();
|
||||||
if (welcomeMessage.SchemaId != MessageType.IdAssigning)
|
if (welcomeMessage.SchemaId != MessageType.IdAssigning)
|
||||||
{
|
{
|
||||||
throw new Exception($"Incorrect message type. Must be IdAssigning, current : {welcomeMessage.SchemaId.ToString()}");
|
throw new Exception($"Incorrect message type. Must be IdAssigning, current : {welcomeMessage.SchemaId.ToString()}");
|
||||||
}
|
}
|
||||||
|
|
||||||
TransmissionConfig.OwnershipRepository = new StaticOwnershipRepository(_serialization.Deserialize<IdAssingnment>(welcomeMessage.Data)!.Id);
|
TransmissionConfig.OwnershipRepository = new StaticOwnershipRepository(_serialization.Deserialize<IdAssingnment>(welcomeMessage.Data)!.Id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,88 +1,92 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
using mROA.Implementation.Backend;
|
using mROA.Implementation.Backend;
|
||||||
using mROA.Implementation.CommandExecution;
|
using mROA.Implementation.CommandExecution;
|
||||||
|
|
||||||
// ReSharper disable MethodHasAsyncOverload
|
// ReSharper disable MethodHasAsyncOverload
|
||||||
|
|
||||||
namespace mROA.Implementation.Frontend;
|
namespace mROA.Implementation.Frontend
|
||||||
|
|
||||||
public class RequestExtractor : IRequestExtractor
|
|
||||||
{
|
{
|
||||||
private IRepresentationModule? _representationModule;
|
public class RequestExtractor : IRequestExtractor
|
||||||
private IContextRepository? _contextRepository;
|
|
||||||
private IMethodRepository? _methodRepository;
|
|
||||||
private IExecuteModule? _executeModule;
|
|
||||||
private ISerializationToolkit? _serializationToolkit;
|
|
||||||
|
|
||||||
public void Inject<T>(T dependency)
|
|
||||||
{
|
{
|
||||||
switch (dependency)
|
private IRepresentationModule? _representationModule;
|
||||||
|
private IContextRepository? _contextRepository;
|
||||||
|
private IMethodRepository? _methodRepository;
|
||||||
|
private IExecuteModule? _executeModule;
|
||||||
|
private ISerializationToolkit? _serializationToolkit;
|
||||||
|
|
||||||
|
public void Inject<T>(T dependency)
|
||||||
{
|
{
|
||||||
case IExecuteModule executeModule:
|
switch (dependency)
|
||||||
_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)
|
|
||||||
{
|
{
|
||||||
var request =
|
case IExecuteModule executeModule:
|
||||||
_representationModule!.GetMessage<DefaultCallRequest>(messageType: MessageType.CallRequest);
|
_executeModule = executeModule;
|
||||||
|
break;
|
||||||
// Console.WriteLine("Executing {0}", request.Id);
|
case IContextRepository contextRepository:
|
||||||
|
_contextRepository = contextRepository;
|
||||||
if (request.Parameter is not null)
|
break;
|
||||||
{
|
case IMethodRepository methodRepository:
|
||||||
var parameterType = _methodRepository!.GetMethod(request.CommandId).GetParameters().First()
|
_methodRepository = methodRepository;
|
||||||
.ParameterType;
|
break;
|
||||||
|
case IRepresentationModule representationModule:
|
||||||
request.Parameter = _serializationToolkit.Cast(request.Parameter, parameterType);
|
_representationModule = representationModule;
|
||||||
}
|
break;
|
||||||
|
case ISerializationToolkit serializationToolkit:
|
||||||
var result = _executeModule.Execute(request, _contextRepository);
|
_serializationToolkit = serializationToolkit;
|
||||||
|
break;
|
||||||
var resultType = result is FinalCommandExecution
|
|
||||||
? MessageType.FinishedCommandExecution
|
|
||||||
: MessageType.ExceptionCommandExecution;
|
|
||||||
|
|
||||||
_representationModule.PostCallMessage(request.Id, resultType, result, result.GetType());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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);
|
multiClientOwnershipRepository?.RegisterOwnership(_representationModule.Id);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
var request =
|
||||||
|
_representationModule!.GetMessage<DefaultCallRequest>(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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,16 +1,24 @@
|
|||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
|
|
||||||
namespace mROA.Implementation.Frontend;
|
namespace mROA.Implementation.Frontend
|
||||||
|
|
||||||
public class StaticOwnershipRepository(int id) : IOwnershipRepository
|
|
||||||
{
|
{
|
||||||
public int GetOwnershipId()
|
public class StaticOwnershipRepository : IOwnershipRepository
|
||||||
{
|
{
|
||||||
return id;
|
private readonly int _id;
|
||||||
}
|
|
||||||
|
|
||||||
public int GetHostOwnershipId()
|
public StaticOwnershipRepository(int id)
|
||||||
{
|
{
|
||||||
return id;
|
_id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetOwnershipId()
|
||||||
|
{
|
||||||
|
return _id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetHostOwnershipId()
|
||||||
|
{
|
||||||
|
return _id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
namespace mROA.Implementation;
|
namespace mROA.Implementation
|
||||||
|
|
||||||
public class IdAssingnment
|
|
||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public class IdAssingnment
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,59 +1,61 @@
|
|||||||
using System.Text.Json;
|
using System;
|
||||||
|
using System.Text.Json;
|
||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
|
|
||||||
namespace mROA.Implementation;
|
namespace mROA.Implementation
|
||||||
|
|
||||||
public class JsonSerializationToolkit : ISerializationToolkit
|
|
||||||
{
|
{
|
||||||
public byte[] Serialize<T>(T objectToSerialize)
|
public class JsonSerializationToolkit : ISerializationToolkit
|
||||||
{
|
{
|
||||||
return JsonSerializer.SerializeToUtf8Bytes(objectToSerialize);
|
public byte[] Serialize<T>(T objectToSerialize)
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] Serialize(object objectToSerialize, Type type)
|
|
||||||
{
|
|
||||||
return JsonSerializer.SerializeToUtf8Bytes(objectToSerialize, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
public T? Deserialize<T>(byte[] rawData)
|
|
||||||
{
|
|
||||||
return JsonSerializer.Deserialize<T>(rawData);
|
|
||||||
}
|
|
||||||
|
|
||||||
public object? Deserialize(byte[] rawData, Type type)
|
|
||||||
{
|
|
||||||
return JsonSerializer.Deserialize(rawData, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
public T? Deserialize<T>(Span<byte> rawData)
|
|
||||||
{
|
|
||||||
return JsonSerializer.Deserialize<T>(rawData);
|
|
||||||
}
|
|
||||||
|
|
||||||
public object? Deserialize(Span<byte> rawData, Type type)
|
|
||||||
{
|
|
||||||
return JsonSerializer.Deserialize(rawData, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
public T Cast<T>(object nonCasted)
|
|
||||||
{
|
|
||||||
return nonCasted switch
|
|
||||||
{
|
{
|
||||||
JsonElement jsonElement => jsonElement.Deserialize<T>()!,
|
return JsonSerializer.SerializeToUtf8Bytes(objectToSerialize);
|
||||||
T casted => casted,
|
}
|
||||||
_ => throw new JsonException("Cannot cast object to type " + typeof(T).FullName)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public object Cast(object nonCasted, Type type)
|
public byte[] Serialize(object objectToSerialize, Type type)
|
||||||
{
|
{
|
||||||
if (nonCasted is JsonElement jsonElement)
|
return JsonSerializer.SerializeToUtf8Bytes(objectToSerialize, type);
|
||||||
return jsonElement.Deserialize(type)!;
|
}
|
||||||
|
|
||||||
throw new JsonException("Cannot cast object to type " + type.FullName);
|
public T? Deserialize<T>(byte[] rawData)
|
||||||
}
|
{
|
||||||
|
return JsonSerializer.Deserialize<T>(rawData);
|
||||||
|
}
|
||||||
|
|
||||||
public void Inject<T>(T dependency)
|
public object? Deserialize(byte[] rawData, Type type)
|
||||||
{
|
{
|
||||||
|
return JsonSerializer.Deserialize(rawData, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T? Deserialize<T>(Span<byte> rawData)
|
||||||
|
{
|
||||||
|
return JsonSerializer.Deserialize<T>(rawData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object? Deserialize(Span<byte> rawData, Type type)
|
||||||
|
{
|
||||||
|
return JsonSerializer.Deserialize(rawData, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T Cast<T>(object nonCasted)
|
||||||
|
{
|
||||||
|
return nonCasted switch
|
||||||
|
{
|
||||||
|
JsonElement jsonElement => jsonElement.Deserialize<T>()!,
|
||||||
|
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>(T dependency)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,43 +1,47 @@
|
|||||||
using System.Reflection;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
using mROA.Implementation.Attributes;
|
using mROA.Implementation.Attributes;
|
||||||
|
|
||||||
namespace mROA.Implementation;
|
namespace mROA.Implementation
|
||||||
|
|
||||||
public class MethodRepository : IMethodRepository
|
|
||||||
{
|
{
|
||||||
private readonly List<MethodInfo> _methods = [];
|
public class MethodRepository : IMethodRepository
|
||||||
|
|
||||||
public MethodInfo GetMethod(int id)
|
|
||||||
{
|
{
|
||||||
if (_methods.Count <= id)
|
private readonly List<MethodInfo> _methods = new() { };
|
||||||
throw new Exception("Method such registered method");
|
|
||||||
|
|
||||||
return _methods[id];
|
public MethodInfo GetMethod(int id)
|
||||||
}
|
|
||||||
|
|
||||||
public int RegisterMethod(MethodInfo method)
|
|
||||||
{
|
|
||||||
_methods.Add(method);
|
|
||||||
return _methods.Count - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<MethodInfo> 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())
|
if (_methods.Count <= id)
|
||||||
RegisterMethod(method);
|
throw new Exception("Method such registered method");
|
||||||
|
|
||||||
|
return _methods[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
public int RegisterMethod(MethodInfo method)
|
||||||
|
{
|
||||||
|
_methods.Add(method);
|
||||||
|
return _methods.Count - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<MethodInfo> 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>(T dependency)
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void Inject<T>(T dependency)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,18 +1,20 @@
|
|||||||
using System.Text.Json.Serialization;
|
using System;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
// ReSharper disable UnusedMember.Global
|
// ReSharper disable UnusedMember.Global
|
||||||
|
|
||||||
namespace mROA.Implementation;
|
namespace mROA.Implementation
|
||||||
|
|
||||||
public class NetworkMessage
|
|
||||||
{
|
{
|
||||||
public Guid Id { get; init; }
|
public class NetworkMessage
|
||||||
[JsonConverter(typeof(JsonStringEnumConverter))]
|
{
|
||||||
public MessageType SchemaId { get; init; }
|
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
|
public enum MessageType
|
||||||
{
|
{
|
||||||
Unknown, FinishedCommandExecution, ExceptionCommandExecution, AsyncCancelCommandExecution, CallRequest, IdAssigning
|
Unknown, FinishedCommandExecution, ExceptionCommandExecution, AsyncCancelCommandExecution, CallRequest, IdAssigning
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
namespace mROA.Implementation
|
||||||
|
|
||||||
public class NextGenerationInteractionModule : INextGenerationInteractionModule
|
|
||||||
{
|
{
|
||||||
private ISerializationToolkit? _serialization;
|
public class NextGenerationInteractionModule : INextGenerationInteractionModule
|
||||||
public int ConnectionId { get; private set; }
|
|
||||||
public Stream? BaseStream { get; set; }
|
|
||||||
private Task<NetworkMessage>? _currentReceiving;
|
|
||||||
private const int BufferSize = ushort.MaxValue;
|
|
||||||
private readonly Memory<byte> _buffer = new byte[BufferSize];
|
|
||||||
private readonly List<NetworkMessage> _messageBuffer = new (128);
|
|
||||||
|
|
||||||
|
|
||||||
public void Inject<T>(T dependency)
|
|
||||||
{
|
{
|
||||||
switch (dependency)
|
private ISerializationToolkit? _serialization;
|
||||||
|
public int ConnectionId { get; private set; }
|
||||||
|
public Stream? BaseStream { get; set; }
|
||||||
|
private Task<NetworkMessage>? _currentReceiving;
|
||||||
|
private const int BufferSize = ushort.MaxValue;
|
||||||
|
private readonly Memory<byte> _buffer = new byte[BufferSize];
|
||||||
|
private readonly List<NetworkMessage> _messageBuffer = new (128);
|
||||||
|
|
||||||
|
|
||||||
|
public void Inject<T>(T dependency)
|
||||||
{
|
{
|
||||||
case ISerializationToolkit toolkit:
|
switch (dependency)
|
||||||
_serialization = toolkit;
|
{
|
||||||
break;
|
case ISerializationToolkit toolkit:
|
||||||
case IIdentityGenerator identityGenerator:
|
_serialization = toolkit;
|
||||||
ConnectionId = identityGenerator.GetNextIdentity();
|
break;
|
||||||
break;
|
case IIdentityGenerator identityGenerator:
|
||||||
|
ConnectionId = identityGenerator.GetNextIdentity();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<NetworkMessage> 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<NetworkMessage> predicate)
|
||||||
|
{
|
||||||
|
return _messageBuffer.FirstOrDefault(m => predicate(m));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<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 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<NetworkMessage>(localSpan.Span);
|
||||||
|
_messageBuffer.Add(message!);
|
||||||
|
_currentReceiving = GetNextMessage();
|
||||||
|
|
||||||
|
return message!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Task<NetworkMessage> 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<NetworkMessage> 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<NetworkMessage>(localSpan);
|
|
||||||
_messageBuffer.Add(message!);
|
|
||||||
_currentReceiving = Task.Run(GetNextMessage);
|
|
||||||
|
|
||||||
return message!;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,57 +1,59 @@
|
|||||||
using System.Collections.Frozen;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
|
|
||||||
namespace mROA.Implementation;
|
namespace mROA.Implementation
|
||||||
|
|
||||||
public class RemoteContextRepository : IContextRepository
|
|
||||||
{
|
{
|
||||||
private IRepresentationModuleProducer? _representationProducer;
|
public class RemoteContextRepository : IContextRepository
|
||||||
public static FrozenDictionary<Type, Type> RemoteTypes = FrozenDictionary<Type, Type>.Empty;
|
|
||||||
public int ResisterObject(object o)
|
|
||||||
{
|
{
|
||||||
throw new NotSupportedException();
|
private IRepresentationModuleProducer? _representationProducer;
|
||||||
}
|
public static Dictionary<Type, Type> RemoteTypes = new();
|
||||||
|
public int ResisterObject(object o)
|
||||||
public void ClearObject(int id)
|
|
||||||
{
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public object GetObject(int id)
|
|
||||||
{
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public T GetObject<T>(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();
|
||||||
}
|
}
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Inject<T>(T dependency)
|
public void ClearObject(int id)
|
||||||
{
|
{
|
||||||
if (dependency is IRepresentationModuleProducer serialisationModule)
|
throw new NotSupportedException();
|
||||||
_representationProducer = serialisationModule;
|
}
|
||||||
|
|
||||||
|
public object GetObject(int id)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T GetObject<T>(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>(T dependency)
|
||||||
|
{
|
||||||
|
if (dependency is IRepresentationModuleProducer serialisationModule)
|
||||||
|
_representationProducer = serialisationModule;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,53 +1,64 @@
|
|||||||
using mROA.Abstract;
|
using System.Threading.Tasks;
|
||||||
|
using mROA.Abstract;
|
||||||
using mROA.Implementation.CommandExecution;
|
using mROA.Implementation.CommandExecution;
|
||||||
|
|
||||||
// ReSharper disable UnusedMember.Global
|
// ReSharper disable UnusedMember.Global
|
||||||
|
|
||||||
namespace mROA.Implementation;
|
namespace mROA.Implementation
|
||||||
|
|
||||||
public abstract class RemoteObjectBase(int id, IRepresentationModule representationModule)
|
|
||||||
{
|
{
|
||||||
public int Id => id;
|
public abstract class RemoteObjectBase
|
||||||
public int OwnerId => representationModule.Id;
|
|
||||||
|
|
||||||
protected async Task<T> GetResultAsync<T>(int methodId, object? parameter = default)
|
|
||||||
{
|
{
|
||||||
var request = new DefaultCallRequest
|
private readonly int _id;
|
||||||
{ CommandId = methodId, ObjectId = id, Parameter = parameter, ParameterType = parameter?.GetType() };
|
private readonly IRepresentationModule _representationModule;
|
||||||
await representationModule.PostCallMessageAsync(request.Id, MessageType.CallRequest, request);
|
|
||||||
|
|
||||||
var successResponse =
|
protected RemoteObjectBase(int id, IRepresentationModule representationModule)
|
||||||
representationModule.GetMessageAsync<FinalCommandExecution<T>>(
|
{
|
||||||
messageType: MessageType.FinishedCommandExecution, requestId: request.Id);
|
_id = id;
|
||||||
var errorResponse =
|
_representationModule = representationModule;
|
||||||
representationModule.GetMessageAsync<ExceptionCommandExecution>(
|
}
|
||||||
messageType: MessageType.ExceptionCommandExecution, requestId: request.Id);
|
|
||||||
Task.WaitAny(successResponse, errorResponse);
|
|
||||||
|
|
||||||
if (successResponse.IsCompletedSuccessfully)
|
public int Id => _id;
|
||||||
return successResponse.Result.Result!;
|
public int OwnerId => _representationModule.Id;
|
||||||
|
|
||||||
throw errorResponse.Result.GetException();
|
protected async Task<T> GetResultAsync<T>(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 successResponse =
|
||||||
{
|
_representationModule.GetMessageAsync<FinalCommandExecution<T>>(
|
||||||
var request = new DefaultCallRequest
|
messageType: MessageType.FinishedCommandExecution, requestId: request.Id);
|
||||||
{ CommandId = methodId, ObjectId = id, Parameter = parameter, ParameterType = parameter?.GetType() };
|
var errorResponse =
|
||||||
await representationModule.PostCallMessageAsync(request.Id, MessageType.CallRequest, request);
|
_representationModule.GetMessageAsync<ExceptionCommandExecution>(
|
||||||
|
messageType: MessageType.ExceptionCommandExecution, requestId: request.Id);
|
||||||
|
Task.WaitAny(successResponse, errorResponse);
|
||||||
|
|
||||||
var successResponse =
|
if (successResponse.IsCompletedSuccessfully)
|
||||||
representationModule.GetMessageAsync<FinalCommandExecution>(
|
return successResponse.Result.Result!;
|
||||||
messageType: MessageType.FinishedCommandExecution, requestId: request.Id);
|
|
||||||
var errorResponse =
|
|
||||||
representationModule.GetMessageAsync<ExceptionCommandExecution>(
|
|
||||||
messageType: MessageType.ExceptionCommandExecution, requestId: request.Id);
|
|
||||||
|
|
||||||
Task.WaitAny(successResponse, errorResponse);
|
throw errorResponse.Result.GetException();
|
||||||
|
}
|
||||||
|
|
||||||
if (successResponse.IsCompletedSuccessfully)
|
protected async Task CallAsync(int methodId, object? parameter = default)
|
||||||
return;
|
{
|
||||||
|
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<FinalCommandExecution>(
|
||||||
|
messageType: MessageType.FinishedCommandExecution, requestId: request.Id);
|
||||||
|
var errorResponse =
|
||||||
|
_representationModule.GetMessageAsync<ExceptionCommandExecution>(
|
||||||
|
messageType: MessageType.ExceptionCommandExecution, requestId: request.Id);
|
||||||
|
|
||||||
|
Task.WaitAny(successResponse, errorResponse);
|
||||||
|
|
||||||
|
if (successResponse.IsCompletedSuccessfully)
|
||||||
|
return;
|
||||||
|
|
||||||
|
throw errorResponse.Result.GetException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,93 +1,96 @@
|
|||||||
using mROA.Abstract;
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using mROA.Abstract;
|
||||||
|
|
||||||
namespace mROA.Implementation;
|
namespace mROA.Implementation
|
||||||
|
|
||||||
public class RepresentationModule : IRepresentationModule
|
|
||||||
{
|
{
|
||||||
private ISerializationToolkit? _serialization;
|
public class RepresentationModule : IRepresentationModule
|
||||||
private INextGenerationInteractionModule? _interaction;
|
|
||||||
|
|
||||||
public void Inject<T>(T dependency)
|
|
||||||
{
|
{
|
||||||
switch (dependency)
|
private ISerializationToolkit? _serialization;
|
||||||
|
private INextGenerationInteractionModule? _interaction;
|
||||||
|
|
||||||
|
public void Inject<T>(T dependency)
|
||||||
{
|
{
|
||||||
case ISerializationToolkit toolkit:
|
switch (dependency)
|
||||||
_serialization = toolkit;
|
|
||||||
break;
|
|
||||||
case INextGenerationInteractionModule interactionModule:
|
|
||||||
_interaction = interactionModule;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Id => (_interaction ?? throw new NullReferenceException("Interaction is not initialized")).ConnectionId;
|
|
||||||
|
|
||||||
public async Task<T> GetMessageAsync<T>(Guid? requestId, MessageType? messageType)
|
|
||||||
{
|
|
||||||
if (_serialization == null)
|
|
||||||
throw new NullReferenceException("Serialization toolkit is not initialized");
|
|
||||||
|
|
||||||
return _serialization.Deserialize<T>(await GetRawMessage(requestId, messageType))!;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T GetMessage<T>(Guid? requestId = null, MessageType? messageType = null)
|
|
||||||
{
|
|
||||||
if (_serialization == null)
|
|
||||||
throw new NullReferenceException("Serialization toolkit is not initialized");
|
|
||||||
|
|
||||||
return _serialization.Deserialize<T>(GetRawMessage(requestId, messageType).GetAwaiter().GetResult())!;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<byte[]> 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();
|
case ISerializationToolkit toolkit:
|
||||||
if ((requestId is not null && message.Id != requestId) ||
|
_serialization = toolkit;
|
||||||
(messageType is not null && message.SchemaId != messageType)) continue;
|
break;
|
||||||
|
case INextGenerationInteractionModule interactionModule:
|
||||||
_interaction.HandleMessage(message);
|
_interaction = interactionModule;
|
||||||
return message.Data;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_interaction.HandleMessage(fromBuffer);
|
public int Id => (_interaction ?? throw new NullReferenceException("Interaction is not initialized")).ConnectionId;
|
||||||
return fromBuffer.Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task PostCallMessageAsync<T>(Guid id, MessageType messageType, T payload) where T : notnull
|
public async Task<T> GetMessageAsync<T>(Guid? requestId, MessageType? messageType)
|
||||||
{
|
{
|
||||||
await PostCallMessageAsync(id, messageType, payload, typeof(T));
|
if (_serialization == null)
|
||||||
}
|
throw new NullReferenceException("Serialization toolkit is not initialized");
|
||||||
|
|
||||||
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
|
return _serialization.Deserialize<T>(await GetRawMessage(requestId, messageType))!;
|
||||||
{ Id = id, SchemaId = messageType, Data = _serialization.Serialize(payload, payloadType) });
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void PostCallMessage<T>(Guid id, MessageType messageType, T payload) where T : notnull
|
public T GetMessage<T>(Guid? requestId = null, MessageType? messageType = null)
|
||||||
{
|
{
|
||||||
PostCallMessageAsync(id, messageType, payload).GetAwaiter().GetResult();
|
if (_serialization == null)
|
||||||
}
|
throw new NullReferenceException("Serialization toolkit is not initialized");
|
||||||
|
|
||||||
|
return _serialization.Deserialize<T>(GetRawMessage(requestId, messageType).GetAwaiter().GetResult())!;
|
||||||
|
}
|
||||||
|
|
||||||
public void PostCallMessage(Guid id, MessageType messageType, object payload, Type payloadType)
|
public async Task<byte[]> GetRawMessage(Guid? requestId = null, MessageType? messageType = null)
|
||||||
{
|
{
|
||||||
PostCallMessageAsync(id, messageType, payload, payloadType).GetAwaiter().GetResult();
|
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<T>(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<T>(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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,101 +1,103 @@
|
|||||||
using System.Text.Json.Serialization;
|
using System;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
// ReSharper disable UnusedMember.Global
|
// ReSharper disable UnusedMember.Global
|
||||||
#pragma warning disable CS8618, CS9264
|
#pragma warning disable CS8618, CS9264
|
||||||
|
|
||||||
namespace mROA.Implementation;
|
namespace mROA.Implementation
|
||||||
|
|
||||||
public static class TransmissionConfig
|
|
||||||
{
|
{
|
||||||
private static IContextRepository? _realContextRepository;
|
public static class TransmissionConfig
|
||||||
private static IContextRepository? _remoteEndpointContextRepository;
|
|
||||||
private static IOwnershipRepository? _ownershipRepository;
|
|
||||||
|
|
||||||
public static IContextRepository RealContextRepository
|
|
||||||
{
|
{
|
||||||
get => _realContextRepository ?? throw new NullReferenceException("RealContextRepository is null");
|
private static IContextRepository? _realContextRepository;
|
||||||
set => _realContextRepository = value;
|
private static IContextRepository? _remoteEndpointContextRepository;
|
||||||
}
|
private static IOwnershipRepository? _ownershipRepository;
|
||||||
|
|
||||||
public static IContextRepository RemoteEndpointContextRepository
|
public static IContextRepository RealContextRepository
|
||||||
{
|
|
||||||
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<T> 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
|
|
||||||
{
|
{
|
||||||
_ownerId = _ownerId == -1 ? TransmissionConfig.OwnershipRepository.GetOwnershipId() : _ownerId;
|
get => _realContextRepository ?? throw new NullReferenceException("RealContextRepository is null");
|
||||||
return _ownerId;
|
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 class SharedObject<T> where T : notnull
|
||||||
public int ContextId
|
|
||||||
{
|
{
|
||||||
// ReSharper disable once UnusedMember.Global
|
private IContextRepository GetDefaultContextRepository() =>
|
||||||
get
|
(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;
|
return _contextId;
|
||||||
|
}
|
||||||
_contextId = TransmissionConfig.RealContextRepository.GetObjectIndex(Value);
|
set
|
||||||
return _contextId;
|
{
|
||||||
|
_contextId = value;
|
||||||
|
Value = GetDefaultContextRepository().GetObject<T>(_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<T>(_contextId)!;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
[JsonIgnore] public T Value { get; private init; }
|
// ReSharper disable once UnusedMember.Global
|
||||||
|
public SharedObject(T value)
|
||||||
// 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)
|
|
||||||
{
|
{
|
||||||
_ownerId = ro.OwnerId;
|
Value = value;
|
||||||
_contextId = ro.Id;
|
|
||||||
|
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<T> value) => value.Value;
|
||||||
|
|
||||||
|
public static implicit operator SharedObject<T>(T value) =>
|
||||||
|
new(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static implicit operator T(SharedObject<T> value) => value.Value;
|
|
||||||
|
|
||||||
public static implicit operator SharedObject<T>(T value) =>
|
|
||||||
new(value);
|
|
||||||
}
|
}
|
||||||
@@ -1,21 +1,23 @@
|
|||||||
using mROA.Abstract;
|
using System;
|
||||||
|
using mROA.Abstract;
|
||||||
|
|
||||||
namespace mROA.Implementation;
|
namespace mROA.Implementation
|
||||||
|
|
||||||
public class StaticRepresentationModuleProducer : IRepresentationModuleProducer
|
|
||||||
{
|
{
|
||||||
private IRepresentationModule? _representationModule;
|
public class StaticRepresentationModuleProducer : IRepresentationModuleProducer
|
||||||
|
{
|
||||||
|
private IRepresentationModule? _representationModule;
|
||||||
|
|
||||||
public IRepresentationModule Produce(int ownership)
|
public IRepresentationModule Produce(int ownership)
|
||||||
{
|
{
|
||||||
if (_representationModule == null)
|
if (_representationModule == null)
|
||||||
throw new NullReferenceException("The representation module is not initialized.");
|
throw new NullReferenceException("The representation module is not initialized.");
|
||||||
return _representationModule;
|
return _representationModule;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Inject<T>(T dependency)
|
public void Inject<T>(T dependency)
|
||||||
{
|
{
|
||||||
if (dependency is IRepresentationModule serialisationModule)
|
if (dependency is IRepresentationModule serialisationModule)
|
||||||
_representationModule = serialisationModule;
|
_representationModule = serialisationModule;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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<int> ReadExactlyAsync(this Stream stream, byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
return await stream.ReadAtLeastAsyncCore(buffer.AsMemory(offset, count), count, true, default);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ValueTask<int> ReadExactlyAsync(this Stream stream, Memory<byte> buffer,
|
||||||
|
CancellationToken cancellationToken = default(CancellationToken))
|
||||||
|
{
|
||||||
|
return stream.ReadAtLeastAsyncCore(buffer, buffer.Length, true, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async ValueTask<int> ReadAtLeastAsyncCore(this Stream stream,
|
||||||
|
Memory<byte> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
-2
@@ -1,8 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net9.0</TargetFramework>
|
<TargetFramework>netstandard2.1</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<Title>mROA</Title>
|
<Title>mROA</Title>
|
||||||
<Version>2.0.0</Version>
|
<Version>2.0.0</Version>
|
||||||
@@ -12,6 +11,11 @@
|
|||||||
<PackageProjectUrl>https://github.com/YaslePoy/mROA</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/YaslePoy/mROA</PackageProjectUrl>
|
||||||
<RepositoryType>git</RepositoryType>
|
<RepositoryType>git</RepositoryType>
|
||||||
<PackageTags>RPC</PackageTags>
|
<PackageTags>RPC</PackageTags>
|
||||||
|
<LangVersion>9</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="System.Text.Json" Version="9.0.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
Reference in New Issue
Block a user