билдится на старом дотнете

This commit is contained in:
2025-02-20 16:10:09 +03:00
parent 5af9408a9a
commit 50fd3e7b73
69 changed files with 1990 additions and 1675 deletions
+4 -2
View File
@@ -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>
+7 -5
View File
@@ -1,11 +1,12 @@
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
{ {
[SharedObjectSingleton]
public class LoadTestImp : ILoadTest
{
public int Next(int last) public int Next(int last)
{ {
return last + 1; return last + 1;
@@ -25,4 +26,5 @@ public class LoadTestImp : ILoadTest
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
}
} }
+4 -3
View File
@@ -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 class Page : IPage
{
public string Text; public string Text;
public byte[] GetData() public byte[] GetData()
{ {
return Encoding.UTF8.GetBytes(Text); return Encoding.UTF8.GetBytes(Text);
} }
}
} }
+6 -4
View File
@@ -1,11 +1,12 @@
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 class Printer : IPrinter
{
public string Name; public string Name;
public string GetName() public string GetName()
{ {
@@ -17,4 +18,5 @@ public class Printer : IPrinter
// 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};
} }
}
} }
+9 -5
View File
@@ -1,13 +1,16 @@
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
{
private List<IPrinter> _printers = new List<IPrinter>();
public SharedObject<IPrinter> Create(string printerName) public SharedObject<IPrinter> Create(string printerName)
{ {
@@ -37,4 +40,5 @@ public class PrinterFactory : IPrinterFactory
Console.WriteLine("Collecting all printers"); Console.WriteLine("Collecting all printers");
return _printers.Select(i => i.GetName()).ToArray(); return _printers.Select(i => i.GetName()).ToArray();
} }
}
} }
+27 -21
View File
@@ -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(); public static void Main(string[] args)
builder.Modules.Add(new BackendIdentityGenerator()); {
builder.UseNetworkGateway(new IPEndPoint(IPAddress.Loopback, 4567), typeof(NextGenerationInteractionModule), var builder = new FullMixBuilder();
builder.UseJsonSerialisation();
builder.Modules.Add(new BackendIdentityGenerator());
builder.UseNetworkGateway(new IPEndPoint(IPAddress.Loopback, 4567), typeof(NextGenerationInteractionModule),
builder.GetModule<IIdentityGenerator>()!); builder.GetModule<IIdentityGenerator>()!);
builder.Modules.Add(new ConnectionHub()); builder.Modules.Add(new ConnectionHub());
builder.Modules.Add(new HubRequestExtractor(typeof(RequestExtractor))); builder.Modules.Add(new HubRequestExtractor(typeof(RequestExtractor)));
builder.UseBasicExecution(); builder.UseBasicExecution();
builder.Modules.Add(new RemoteContextRepository()); builder.Modules.Add(new RemoteContextRepository());
// builder.UseCollectableContextRepository(typeof(PrinterFactory).Assembly); // builder.UseCollectableContextRepository(typeof(PrinterFactory).Assembly);
builder.Modules.Add(new MultiClientContextRepository(i => builder.Modules.Add(new MultiClientContextRepository(i =>
{ {
var repo = new ContextRepository(); var repo = new ContextRepository();
repo.FillSingletons(typeof(PrinterFactory).Assembly); repo.FillSingletons(typeof(PrinterFactory).Assembly);
return repo; return repo;
})); }));
builder.SetupMethodsRepository(new CoCodegenMethodRepository()); builder.SetupMethodsRepository(new CoCodegenMethodRepository());
builder.Modules.Add(new CreativeRepresentationModuleProducer([builder.GetModule<JsonSerializationToolkit>()!], builder.Modules.Add(new CreativeRepresentationModuleProducer(
new IInjectableModule[] { builder.GetModule<JsonSerializationToolkit>()! },
typeof(RepresentationModule))); typeof(RepresentationModule)));
builder.Build(); builder.Build();
new RemoteTypeBinder(); new RemoteTypeBinder();
TransmissionConfig.RealContextRepository = builder.GetModule<MultiClientContextRepository>(); TransmissionConfig.RealContextRepository = builder.GetModule<MultiClientContextRepository>();
TransmissionConfig.RemoteEndpointContextRepository = builder.GetModule<RemoteContextRepository>(); TransmissionConfig.RemoteEndpointContextRepository = builder.GetModule<RemoteContextRepository>();
TransmissionConfig.OwnershipRepository = new MultiClientOwnershipRepository(); TransmissionConfig.OwnershipRepository = new MultiClientOwnershipRepository();
var gateway = builder.GetModule<IGatewayModule>(); var gateway = builder.GetModule<IGatewayModule>();
gateway.Run(); gateway.Run();
}
}
+12 -8
View File
@@ -1,10 +1,13 @@
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 class ClientBasedPrinter : IPrinter
{
public string GetName() public string GetName()
{ {
Console.WriteLine("ClientBasedPrinter called from server!!!!!!!!!!! Vova likes that:)"); Console.WriteLine("ClientBasedPrinter called from server!!!!!!!!!!! Vova likes that:)");
@@ -17,12 +20,13 @@ public class ClientBasedPrinter : IPrinter
await Task.Yield(); await Task.Yield();
return new ClientBasedPage(); return new ClientBasedPage();
} }
} }
public class ClientBasedPage : IPage public class ClientBasedPage : IPage
{ {
public byte[] GetData() public byte[] GetData()
{ {
return [1, 2, 3]; return new byte[] { 1, 2, 3 };
}
} }
} }
+4 -2
View File
@@ -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>
+60 -52
View File
@@ -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");
}
}
+4 -2
View File
@@ -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>
+5 -4
View File
@@ -1,13 +1,14 @@
using mROA.Implementation.Attributes; using mROA.Implementation.Attributes;
namespace Example.Shared; namespace Example.Shared
[SharedObjectInterface]
public interface ILoadTest
{ {
[SharedObjectInterface]
public interface ILoadTest
{
int Next(int last); int Next(int last);
int Last(int next); int Last(int next);
void C(); void C();
void A(); void A();
}
} }
+5 -4
View File
@@ -1,9 +1,10 @@
using mROA.Implementation.Attributes; using mROA.Implementation.Attributes;
namespace Example.Shared; namespace Example.Shared
[SharedObjectInterface]
public interface IPage
{ {
[SharedObjectInterface]
public interface IPage
{
byte[] GetData(); byte[] GetData();
}
} }
+7 -4
View File
@@ -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
{ {
[SharedObjectInterface]
public interface IPrinter
{
string GetName(); string GetName();
Task<SharedObject<IPage>> Print(string text, CancellationToken cancellationToken); Task<SharedObject<IPage>> Print(string text, CancellationToken cancellationToken);
}
} }
+5 -4
View File
@@ -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
{ {
[SharedObjectInterface]
public interface IPrinterFactory
{
SharedObject<IPrinter> Create(string printerName); SharedObject<IPrinter> Create(string printerName);
void Register(SharedObject<IPrinter> printer); void Register(SharedObject<IPrinter> printer);
SharedObject<IPrinter> GetPrinterByName(string printerName); SharedObject<IPrinter> GetPrinterByName(string printerName);
SharedObject<IPrinter> GetFirstPrinter(); SharedObject<IPrinter> GetFirstPrinter();
string[] CollectAllNames(); string[] CollectAllNames();
}
} }
+11 -7
View File
@@ -1,20 +1,23 @@
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
{ {
class Program
{
static void Main(string[] args) static void Main(string[] args)
{ {
Console.WriteLine("Hello, World!"); Console.WriteLine("Hello, World!");
var summary = BenchmarkRunner.Run<CollectionsSpeed>(); var summary = BenchmarkRunner.Run<CollectionsSpeed>();
} }
} }
public class CollectionsSpeed public class CollectionsSpeed
{ {
private const int N = 1000; private const int N = 1000;
private readonly List<int> _immutable; private readonly List<int> _immutable;
@@ -47,4 +50,5 @@ public class CollectionsSpeed
} }
return sum; return sum;
} }
}
} }
+2 -2
View File
@@ -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>
+1 -2
View File
@@ -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>
+124 -62
View File
@@ -7,15 +7,15 @@ 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
{ {
/// <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 : ISourceGenerator
{
private const string Namespace = "mROA.Implementation"; private const string Namespace = "mROA.Implementation";
private const string AttributeName = "SharedObjectInterafceAttribute"; private const string AttributeName = "SharedObjectInterafceAttribute";
@@ -29,47 +29,47 @@ 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. // // Generate the source code.
context.RegisterSourceOutput(context.CompilationProvider.Combine(provider.Collect()), // context.RegisterSourceOutput(context.CompilationProvider.Combine(provider.Collect()),
((ctx, t) => GenerateCode(ctx, t.Left, t.Right))); // ((ctx, t) => GenerateCode(ctx, t.Left, t.Right)));
} // }
/// <summary> /// <summary>
/// Checks whether the Node is annotated with the [Report] attribute and maps syntax context to the specific node type (ClassDeclarationSyntax). /// Checks whether the Node is annotated with the [Report] attribute and maps syntax context to the specific node type (ClassDeclarationSyntax).
/// </summary> /// </summary>
/// <param name="context">Syntax context, based on CreateSyntaxProvider predicate</param> /// <param name="context">Syntax context, based on CreateSyntaxProvider predicate</param>
/// <returns>The specific cast and whether the attribute was found.</returns> /// <returns>The specific cast and whether the attribute was found.</returns>
private static (InterfaceDeclarationSyntax, bool reportAttributeFound) GetClassDeclarationForSourceGen( // private static (InterfaceDeclarationSyntax, bool reportAttributeFound) GetClassDeclarationForSourceGen(
GeneratorSyntaxContext context) // GeneratorSyntaxContext context)
{ // {
var classDeclarationSyntax = (InterfaceDeclarationSyntax)context.Node; // var classDeclarationSyntax = (InterfaceDeclarationSyntax)context.Node;
//
// Go through all attributes of the class. // // Go through all attributes of the class.
foreach (AttributeListSyntax attributeListSyntax in classDeclarationSyntax.AttributeLists) // foreach (AttributeListSyntax attributeListSyntax in classDeclarationSyntax.AttributeLists)
foreach (AttributeSyntax attributeSyntax in attributeListSyntax.Attributes) // foreach (AttributeSyntax attributeSyntax in attributeListSyntax.Attributes)
{ // {
if (context.SemanticModel.GetSymbolInfo(attributeSyntax).Symbol is not IMethodSymbol attributeSymbol) // if (context.SemanticModel.GetSymbolInfo(attributeSyntax).Symbol is not IMethodSymbol attributeSymbol)
continue; // if we can't get the symbol, ignore it // continue; // if we can't get the symbol, ignore it
//
string attributeName = attributeSymbol.ContainingType.ToDisplayString(); // string attributeName = attributeSymbol.ContainingType.ToDisplayString();
//
// Check the full name of the [Report] attribute. // // Check the full name of the [Report] attribute.
if (attributeName == "mROA.Implementation.Attributes.SharedObjectInterfaceAttribute") // if (attributeName == "mROA.Implementation.Attributes.SharedObjectInterfaceAttribute")
return (classDeclarationSyntax, true); // return (classDeclarationSyntax, true);
} // }
//
return (classDeclarationSyntax, false); // return (classDeclarationSyntax, false);
} // }
/// <summary> /// <summary>
/// Generate code action. /// Generate code action.
@@ -78,7 +78,7 @@ namespace {Namespace}
/// <param name="context">Source generation context used to add source files.</param> /// <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="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> /// <param name="classes">Nodes annotated with the [Report] attribute that trigger the generate action.</param>
private void GenerateCode(SourceProductionContext context, Compilation compilation, private void GenerateCode(GeneratorExecutionContext context, Compilation compilation,
ImmutableArray<InterfaceDeclarationSyntax> classes) ImmutableArray<InterfaceDeclarationSyntax> classes)
{ {
var methods = new List<(string, IMethodSymbol)>(); var methods = new List<(string, IMethodSymbol)>();
@@ -133,7 +133,7 @@ namespace {Namespace}
var prefix = isAsync ? "await " : ""; var prefix = isAsync ? "await " : "";
var postfix = !isAsync ? (isVoid? ".Wait()" : ".GetAwaiter().GetResult()") : ""; var postfix = !isAsync ? (isVoid ? ".Wait()" : ".GetAwaiter().GetResult()") : "";
var parameterLink = isParametrized ? ", " + method.Parameters.First().Name : string.Empty; var parameterLink = isParametrized ? ", " + method.Parameters.First().Name : string.Empty;
var caller = isVoid ? $"CallAsync({index}{parameterLink})" : var caller = isVoid ? $"CallAsync({index}{parameterLink})" :
isAsync ? $"GetResultAsync<{ExtractTaskType(method.ReturnType)}>({index}{parameterLink})" : isAsync ? $"GetResultAsync<{ExtractTaskType(method.ReturnType)}>({index}{parameterLink})" :
@@ -166,9 +166,9 @@ namespace {Namespace}
// //
// sb.AppendLine("\t}"); // sb.AppendLine("\t}");
sb.AppendLine("\t\t" + prefix + caller + postfix+ ";"); sb.AppendLine("\t\t\t" + prefix + caller + postfix + ";");
sb.AppendLine("\t}"); sb.AppendLine("\t\t}");
methodsText.Add(sb.ToString()); methodsText.Add(sb.ToString());
} }
@@ -181,19 +181,21 @@ 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}
{{ {{
partial class {className} : RemoteObjectBase, {originalName}
{{
public {className}(int id, IRepresentationModule representationModule) : base(id, representationModule) 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. // Add the source code to the compilation.
context.AddSource($"{className}.g.cs", SourceText.From(code, Encoding.UTF8)); context.AddSource($"{className}.g.cs", SourceText.From(code, Encoding.UTF8));
@@ -204,21 +206,23 @@ partial class {className} : RemoteObjectBase, {originalName}
if (methods.Count != 0) if (methods.Count != 0)
{ {
var methodsStringed = methods.Select(i => var methodsStringed = methods.Select(i =>
$"typeof({i.Item1}).GetMethod(\"{i.Item2.Name}\", [{string.Join(", ", i.Item2.Parameters.Select(p => $"typeof({p.Type.ToDisplayString()})"))}])") $"typeof({i.Item1}).GetMethod(\"{i.Item2.Name}\", new Type[] {{{string.Join(", ", i.Item2.Parameters.Select(p => $"typeof({p.Type.ToDisplayString()})"))}}})")
.ToList(); .ToList();
var coCodegenRepoCode = @$"// <auto-generated/> 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)} {{
]; private readonly List<MethodInfo> _methods = new () {{
{string.Join(",\r\n\t\t\t", methodsStringed)}
}};
public MethodInfo GetMethod(int id) public MethodInfo GetMethod(int id)
{{ {{
if (_methods.Count <= id) if (_methods.Count <= id)
@@ -241,6 +245,7 @@ public class CoCodegenMethodRepository : IMethodRepository
public void Inject<T>(T dependency) 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));
@@ -249,17 +254,20 @@ public class CoCodegenMethodRepository : IMethodRepository
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
{{ {{
public sealed class RemoteTypeBinder
{{
static RemoteTypeBinder(){{ static RemoteTypeBinder(){{
RemoteContextRepository.RemoteTypes = new Dictionary<Type, Type> {{ RemoteContextRepository.RemoteTypes = new Dictionary<Type, Type> {{
{string.Join(", \r\n\t\t", frontendContextRepo)}}}.ToFrozenDictionary(); {string.Join(", \r\n\t\t\t", frontendContextRepo)}}};
}}
}} }}
}} }}
"; ";
@@ -283,4 +291,58 @@ public sealed class RemoteTypeBinder
type = type.Substring(type.IndexOf('<') + 1); type = type.Substring(type.IndexOf('<') + 1);
return type.Substring(0, type.Length - 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;
}
}
} }
+9 -5
View File
@@ -1,16 +1,19 @@
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
{ {
public class NextGenTest
{
private TcpListener _listener; private TcpListener _listener;
private NextGenerationInteractionModule _interactionModuleA; private NextGenerationInteractionModule _interactionModuleA;
private NextGenerationInteractionModule _interactionModuleB; private NextGenerationInteractionModule _interactionModuleB;
private Guid[] guids = [Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid()]; private Guid[] guids = new[] { Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid() };
[SetUp] [SetUp]
public void Setup() public void Setup()
@@ -69,4 +72,5 @@ public class NextGenTest
{ {
_listener.Dispose(); _listener.Dispose();
} }
}
} }
+2 -2
View File
@@ -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>
+6 -3
View File
@@ -1,8 +1,11 @@
namespace mROA.Abstract; using System;
public interface ICommandExecution namespace mROA.Abstract
{ {
Guid Id { get; init; } public interface ICommandExecution
{
Guid Id { get; set; }
int ClientId { get; set; } int ClientId { get; set; }
int CommandId { get; } int CommandId { get; }
}
} }
+7 -6
View File
@@ -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
{ {
public delegate void ConnectionHandler(IRepresentationModule representationModule);
public delegate void DisconnectionHandler(IRepresentationModule representationModule);
public interface IConnectionHub : IInjectableModule
{
void RegisterInteraction(INextGenerationInteractionModule interaction); void RegisterInteraction(INextGenerationInteractionModule interaction);
INextGenerationInteractionModule GetInteracion(int id); INextGenerationInteractionModule GetInteracion(int id);
event ConnectionHandler? OnConnected; event ConnectionHandler? OnConnected;
event DisconnectionHandler? OnDisconnected; event DisconnectionHandler? OnDisconnected;
}
} }
+5 -2
View File
@@ -1,11 +1,14 @@
namespace mROA.Abstract; using System;
public interface IContextRepository : IInjectableModule namespace mROA.Abstract
{ {
public interface IContextRepository : IInjectableModule
{
int ResisterObject(object o); int ResisterObject(object o);
void ClearObject(int id); void ClearObject(int id);
object GetObject(int id); object GetObject(int id);
T? GetObject<T>(int id); T? GetObject<T>(int id);
object GetSingleObject(Type type); object GetSingleObject(Type type);
int GetObjectIndex(object o); int GetObjectIndex(object o);
}
} }
+4 -3
View File
@@ -1,6 +1,7 @@
namespace mROA.Abstract; namespace mROA.Abstract
public interface IContextRepositoryHub
{ {
public interface IContextRepositoryHub
{
IContextRepository GetRepository(int clientId); IContextRepository GetRepository(int clientId);
}
} }
+4 -3
View File
@@ -1,8 +1,9 @@
using mROA.Implementation; using mROA.Implementation;
namespace mROA.Abstract; namespace mROA.Abstract
public interface IExecuteModule : IInjectableModule
{ {
public interface IExecuteModule : IInjectableModule
{
ICommandExecution Execute(ICallRequest command, IContextRepository contextRepository); ICommandExecution Execute(ICallRequest command, IContextRepository contextRepository);
}
} }
+6 -2
View File
@@ -1,3 +1,7 @@
namespace mROA.Abstract; namespace mROA.Abstract
{
public interface IFrontendBridge : IInjectableModule
{
public interface IFrontendBridge : IInjectableModule; }
}
+5 -2
View File
@@ -1,6 +1,9 @@
namespace mROA.Abstract; using System;
public interface IGatewayModule : IDisposable, IInjectableModule namespace mROA.Abstract
{ {
public interface IGatewayModule : IDisposable, IInjectableModule
{
void Run(); void Run();
}
} }
+4 -3
View File
@@ -1,6 +1,7 @@
namespace mROA.Abstract; namespace mROA.Abstract
public interface IIdentityGenerator : IInjectableModule
{ {
public interface IIdentityGenerator : IInjectableModule
{
int GetNextIdentity(); int GetNextIdentity();
}
} }
+4 -3
View File
@@ -1,6 +1,7 @@
namespace mROA.Abstract; namespace mROA.Abstract
public interface IInjectableModule
{ {
public interface IInjectableModule
{
void Inject<T>(T dependency); void Inject<T>(T dependency);
}
} }
+7 -3
View File
@@ -1,9 +1,12 @@
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
{ {
public interface INextGenerationInteractionModule : IInjectableModule
{
int ConnectionId { get; } int ConnectionId { get; }
public Stream? BaseStream { get; set; } public Stream? BaseStream { get; set; }
Task<NetworkMessage> GetNextMessageReceiving(); Task<NetworkMessage> GetNextMessageReceiving();
@@ -11,4 +14,5 @@ public interface INextGenerationInteractionModule : IInjectableModule
void HandleMessage(NetworkMessage message); void HandleMessage(NetworkMessage message);
NetworkMessage[] UnhandledMessages { get; } NetworkMessage[] UnhandledMessages { get; }
NetworkMessage? FirstByFilter(Predicate<NetworkMessage> predicate); NetworkMessage? FirstByFilter(Predicate<NetworkMessage> predicate);
}
} }
+6 -4
View File
@@ -1,11 +1,13 @@
using System.Reflection; using System.Collections.Generic;
using System.Reflection;
namespace mROA.Abstract; namespace mROA.Abstract
public interface IMethodRepository : IInjectableModule
{ {
public interface IMethodRepository : IInjectableModule
{
MethodInfo GetMethod(int id); MethodInfo GetMethod(int id);
int RegisterMethod(MethodInfo method); int RegisterMethod(MethodInfo method);
IEnumerable<MethodInfo> GetMethods(); IEnumerable<MethodInfo> GetMethods();
}
} }
+4 -3
View File
@@ -1,7 +1,8 @@
namespace mROA.Abstract; namespace mROA.Abstract
public interface IOwnershipRepository
{ {
public interface IOwnershipRepository
{
int GetOwnershipId(); int GetOwnershipId();
int GetHostOwnershipId(); int GetHostOwnershipId();
}
} }
@@ -1,6 +1,7 @@
namespace mROA.Abstract; namespace mROA.Abstract
public interface IRepresentationModuleProducer : IInjectableModule
{ {
public interface IRepresentationModuleProducer : IInjectableModule
{
IRepresentationModule Produce(int id); IRepresentationModule Produce(int id);
}
} }
+5 -2
View File
@@ -1,6 +1,9 @@
namespace mROA.Abstract; using System.Threading.Tasks;
public interface IRequestExtractor : IInjectableModule namespace mROA.Abstract
{ {
public interface IRequestExtractor : IInjectableModule
{
Task StartExtraction(); Task StartExtraction();
}
} }
+9 -6
View File
@@ -1,10 +1,12 @@
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
{ {
public interface ISerialisationModule : IInjectableModule
{
void HandleIncomingRequest(int clientId, byte[] message); void HandleIncomingRequest(int clientId, byte[] message);
void PostResponse(NetworkMessage message, int clientId); void PostResponse(NetworkMessage message, int clientId);
void SendWelcomeMessage(int clientId); void SendWelcomeMessage(int clientId);
@@ -15,10 +17,10 @@ public interface ISerialisationModule : IInjectableModule
Task<FinalCommandExecution<T>> GetFinalCommandExecution<T>(Guid requestId); Task<FinalCommandExecution<T>> GetFinalCommandExecution<T>(Guid requestId);
void PostCallRequest(ICallRequest callRequest); 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);
@@ -28,4 +30,5 @@ public interface IRepresentationModule : IInjectableModule
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);
}
} }
+5 -2
View File
@@ -1,7 +1,9 @@
namespace mROA.Abstract; using System;
public interface ISerializationToolkit : IInjectableModule namespace mROA.Abstract
{ {
public interface ISerializationToolkit : IInjectableModule
{
byte[] Serialize<T>(T objectToSerialize); byte[] Serialize<T>(T objectToSerialize);
byte[] Serialize(object objectToSerialize, Type type); byte[] Serialize(object objectToSerialize, Type type);
T? Deserialize<T>(byte[] rawData); T? Deserialize<T>(byte[] rawData);
@@ -11,4 +13,5 @@ public interface ISerializationToolkit : IInjectableModule
T Cast<T>(object nonCasted); T Cast<T>(object nonCasted);
object Cast(object nonCasted, Type type); 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,9 +1,9 @@
using mROA.Abstract; using mROA.Abstract;
namespace mROA.Implementation.Backend; namespace mROA.Implementation.Backend
public class BackendIdentityGenerator : IIdentityGenerator
{ {
public class BackendIdentityGenerator : IIdentityGenerator
{
private int _currentId; private int _currentId;
public int GetNextIdentity() public int GetNextIdentity()
@@ -14,4 +14,5 @@ public class BackendIdentityGenerator : IIdentityGenerator
public void Inject<T>(T dependency) public void Inject<T>(T dependency)
{ {
} }
}
} }
@@ -1,12 +1,13 @@
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 class BasicConfigurationExtensions
{
public static void UseJsonSerialisation(this FullMixBuilder builder) public static void UseJsonSerialisation(this FullMixBuilder builder)
{ {
builder.Modules.Add(new JsonSerializationToolkit()); builder.Modules.Add(new JsonSerializationToolkit());
@@ -34,4 +35,5 @@ public static class BasicConfigurationExtensions
{ {
builder.Modules.Add(methodRepository); builder.Modules.Add(methodRepository);
} }
}
} }
@@ -1,11 +1,14 @@
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
{ {
public class BasicExecutionModule : IExecuteModule
{
private IMethodRepository? _methodRepo; private IMethodRepository? _methodRepo;
public void Inject<T>(T dependency) public void Inject<T>(T dependency)
@@ -45,7 +48,8 @@ public class BasicExecutionModule : IExecuteModule
{ {
try try
{ {
var finalResult = currentCommand.Invoke(context, parameter is null ? [] : [parameter]); var finalResult = currentCommand.Invoke(context, parameter is null ? new object[0] : new[]
{ parameter });
return new TypedFinalCommandExecution return new TypedFinalCommandExecution
{ {
CommandId = command.CommandId, Result = finalResult, CommandId = command.CommandId, Result = finalResult,
@@ -70,7 +74,8 @@ public class BasicExecutionModule : IExecuteModule
var token = tokenSource.Token; var token = tokenSource.Token;
try try
{ {
var result = (Task)currentCommand.Invoke(context, parameter is null ? [token] : [parameter, token])!; var result = (Task)currentCommand.Invoke(context, parameter is null ? new object[] { token } : new[]
{ parameter, token })!;
result.Wait(token); result.Wait(token);
@@ -96,7 +101,8 @@ public class BasicExecutionModule : IExecuteModule
try try
{ {
var result = var result =
(Task)currentCommand.Invoke(context, parameter is null ? [token] : [parameter, token])!; (Task)currentCommand.Invoke(context, parameter is null ? new object[] { token } : new[]
{ parameter, token })!;
result.Wait(token); result.Wait(token);
@@ -118,4 +124,5 @@ public class BasicExecutionModule : IExecuteModule
}; };
} }
} }
}
} }
+7 -4
View File
@@ -1,9 +1,11 @@
using mROA.Abstract; using System;
using System.Collections.Generic;
using mROA.Abstract;
namespace mROA.Implementation.Backend; namespace mROA.Implementation.Backend
public class ConnectionHub : IConnectionHub
{ {
public class ConnectionHub : IConnectionHub
{
private readonly Dictionary<int, INextGenerationInteractionModule> _connections = new(); private readonly Dictionary<int, INextGenerationInteractionModule> _connections = new();
private ISerializationToolkit? _serializationToolkit; private ISerializationToolkit? _serializationToolkit;
@@ -32,4 +34,5 @@ public class ConnectionHub : IConnectionHub
_serializationToolkit = serializationToolkit; _serializationToolkit = serializationToolkit;
} }
}
} }
@@ -1,13 +1,16 @@
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 Dictionary<int, object?>? _singletons;
private object?[] _storage = new object[StartupSize]; private object?[] _storage = new object[StartupSize];
private Task<int> _lastIndexFinder = Task.FromResult(0); private Task<int> _lastIndexFinder = Task.FromResult(0);
@@ -22,7 +25,7 @@ public class ContextRepository : IContextRepository
type is { IsClass: true, IsAbstract: false, IsGenericType: false } && type is { IsClass: true, IsAbstract: false, IsGenericType: false } &&
type.GetCustomAttributes(typeof(SharedObjectSingletonAttribute), true).Length > 0); type.GetCustomAttributes(typeof(SharedObjectSingletonAttribute), true).Length > 0);
_singletons = _singletons =
types.ToFrozenDictionary( types.ToDictionary(
t => t.GetInterfaces().FirstOrDefault(i => t => t.GetInterfaces().FirstOrDefault(i =>
i.GetCustomAttributes(typeof(SharedObjectInterfaceAttribute), true).Length > 0)!.GetHashCode(), i.GetCustomAttributes(typeof(SharedObjectInterfaceAttribute), true).Length > 0)!.GetHashCode(),
Activator.CreateInstance); Activator.CreateInstance);
@@ -85,4 +88,5 @@ public class ContextRepository : IContextRepository
{ {
} }
}
} }
@@ -1,15 +1,22 @@
using System;
using mROA.Abstract; using mROA.Abstract;
namespace mROA.Implementation.Backend; namespace mROA.Implementation.Backend
public class HubRequestExtractor(Type extractoType) : IInjectableModule
{ {
public class HubRequestExtractor : IInjectableModule
{
private IConnectionHub? _hub; private IConnectionHub? _hub;
private IContextRepository? _contextRepository; private IContextRepository? _contextRepository;
private IMethodRepository? _methodRepository; private IMethodRepository? _methodRepository;
private ISerializationToolkit? _serializationToolkit; private ISerializationToolkit? _serializationToolkit;
private IExecuteModule? _executeModule; private IExecuteModule? _executeModule;
private readonly Type _extractorType;
public HubRequestExtractor(Type extractorType)
{
_extractorType = extractorType;
}
public void Inject<T>(T dependency) public void Inject<T>(T dependency)
{ {
@@ -36,7 +43,7 @@ public class HubRequestExtractor(Type extractoType) : IInjectableModule
private void HubOnOnConnected(IRepresentationModule interaction) private void HubOnOnConnected(IRepresentationModule interaction)
{ {
var extractor = (IRequestExtractor)Activator.CreateInstance(extractoType)!; var extractor = (IRequestExtractor)Activator.CreateInstance(_extractorType)!;
extractor.Inject(interaction); extractor.Inject(interaction);
if (_contextRepository is IContextRepositoryHub contextHub) if (_contextRepository is IContextRepositoryHub contextHub)
extractor.Inject(contextHub.GetRepository(interaction.Id)); extractor.Inject(contextHub.GetRepository(interaction.Id));
@@ -47,4 +54,5 @@ public class HubRequestExtractor(Type extractoType) : IInjectableModule
extractor.Inject(_executeModule); extractor.Inject(_executeModule);
_ = extractor.StartExtraction(); _ = extractor.StartExtraction();
} }
}
} }
@@ -1,17 +1,25 @@
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
{ {
public class MultiClientContextRepository : IContextRepository, IContextRepositoryHub
{
private Dictionary<int, IContextRepository> _repositories = new(); private Dictionary<int, IContextRepository> _repositories = new();
private readonly Func<int, IContextRepository> _produceRepository;
public MultiClientContextRepository(Func<int, IContextRepository> produceRepository)
{
_produceRepository = produceRepository;
}
private IContextRepository GetRepositoryByClientId(int clientId) private IContextRepository GetRepositoryByClientId(int clientId)
{ {
if (_repositories.TryGetValue(clientId, out var repository)) if (_repositories.TryGetValue(clientId, out var repository))
return repository; return repository;
var created = produceRepository(clientId); var created = _produceRepository(clientId);
_repositories.Add(clientId, created); _repositories.Add(clientId, created);
return created; return created;
} }
@@ -53,4 +61,5 @@ public class MultiClientContextRepository(Func<int, IContextRepository> produceR
{ {
return GetRepositoryByClientId(clientId); return GetRepositoryByClientId(clientId);
} }
}
} }
@@ -1,9 +1,11 @@
using mROA.Abstract; using System;
using System.Collections.Generic;
using mROA.Abstract;
namespace mROA.Implementation.Backend; namespace mROA.Implementation.Backend
public class MultiClientOwnershipRepository : IOwnershipRepository
{ {
public class MultiClientOwnershipRepository : IOwnershipRepository
{
private Dictionary<int, int> _ownerships = new(); private Dictionary<int, int> _ownerships = new();
public int GetOwnershipId() public int GetOwnershipId()
@@ -25,4 +27,5 @@ public class MultiClientOwnershipRepository : IOwnershipRepository
{ {
_ownerships.Remove(Environment.CurrentManagedThreadId); _ownerships.Remove(Environment.CurrentManagedThreadId);
} }
}
} }
@@ -1,11 +1,13 @@
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
{ {
public class NetworkGatewayModule : IGatewayModule
{
private readonly Type? _interactionModuleType; private readonly Type? _interactionModuleType;
private readonly IInjectableModule[]? _injectableModules; private readonly IInjectableModule[]? _injectableModules;
private readonly TcpListener _tcpListener; private readonly TcpListener _tcpListener;
@@ -40,7 +42,6 @@ public class NetworkGatewayModule : IGatewayModule
public void Dispose() public void Dispose()
{ {
_tcpListener.Stop(); _tcpListener.Stop();
_tcpListener.Dispose();
} }
private void HandleIncomingConnections() private void HandleIncomingConnections()
@@ -86,4 +87,5 @@ public class NetworkGatewayModule : IGatewayModule
if (dependency is ISerializationToolkit serializationToolkit) if (dependency is ISerializationToolkit serializationToolkit)
_serialization = serializationToolkit; _serialization = serializationToolkit;
} }
}
} }
@@ -1,10 +1,12 @@
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 List<IInjectableModule> Modules { get; } = new() { };
public void Build() public void Build()
{ {
@@ -17,4 +19,5 @@ public class FullMixBuilder
{ {
return Modules.OfType<T>().FirstOrDefault(); return Modules.OfType<T>().FirstOrDefault();
} }
}
} }
+12 -10
View File
@@ -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
{ {
public interface ICallRequest
{
Guid Id { get; } Guid Id { get; }
int CommandId { get; } int CommandId { get; }
int ObjectId { get; } int ObjectId { get; }
object? Parameter { 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 Guid Id { get; set; }
public int ClientId { get; set; } public int ClientId { get; set; }
public int CommandId { get; init; } public int CommandId { get; set; }
public required string Exception { get; set; } public string Exception { get; set; }
public RemoteException GetException() public RemoteException GetException()
{ {
return new RemoteException(Exception) { CallRequestId = Id }; 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
{
public Guid Id { get; set; }
[JsonIgnore] [JsonIgnore]
public int ClientId { get; set; } public int ClientId { get; set; }
[JsonIgnore] [JsonIgnore]
public int CommandId { get; init; } 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>
{ {
public class TypedFinalCommandExecution : FinalCommandExecution<object>
{
[JsonIgnore] [JsonIgnore]
// ReSharper disable once UnusedAutoPropertyAccessor.Global // ReSharper disable once UnusedAutoPropertyAccessor.Global
public Type? Type { get; set; } public Type? Type { get; set; }
}
} }
@@ -1,9 +1,10 @@
using mROA.Abstract; using System;
using mROA.Abstract;
namespace mROA.Implementation; namespace mROA.Implementation
public class CreativeRepresentationModuleProducer : IRepresentationModuleProducer
{ {
public class CreativeRepresentationModuleProducer : IRepresentationModuleProducer
{
private Type _reprModuleType; private Type _reprModuleType;
private IInjectableModule[] _creationModules; private IInjectableModule[] _creationModules;
private IConnectionHub? _hub; private IConnectionHub? _hub;
@@ -37,4 +38,5 @@ public class CreativeRepresentationModuleProducer : IRepresentationModuleProduce
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,14 +1,21 @@
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
{ {
public class NetworkFrontendBridge : IFrontendBridge
{
private readonly TcpClient _tcpClient = new(); private readonly TcpClient _tcpClient = new();
private NextGenerationInteractionModule? _interactionModule; private NextGenerationInteractionModule? _interactionModule;
private ISerializationToolkit? _serialization; private ISerializationToolkit? _serialization;
private readonly IPEndPoint _ipEndPoint;
public NetworkFrontendBridge(IPEndPoint ipEndPoint)
{
_ipEndPoint = ipEndPoint;
}
public void Inject<T>(T dependency) public void Inject<T>(T dependency)
{ {
@@ -30,7 +37,7 @@ public class NetworkFrontendBridge(IPEndPoint ipEndPoint) : IFrontendBridge
if (_serialization == null) if (_serialization == null)
throw new NullReferenceException("Serialization toolkit is not initialized"); 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)
@@ -40,4 +47,5 @@ public class NetworkFrontendBridge(IPEndPoint ipEndPoint) : IFrontendBridge
TransmissionConfig.OwnershipRepository = new StaticOwnershipRepository(_serialization.Deserialize<IdAssingnment>(welcomeMessage.Data)!.Id); TransmissionConfig.OwnershipRepository = new StaticOwnershipRepository(_serialization.Deserialize<IdAssingnment>(welcomeMessage.Data)!.Id);
} }
}
} }
@@ -1,13 +1,16 @@
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
{ {
public class RequestExtractor : IRequestExtractor
{
private IRepresentationModule? _representationModule; private IRepresentationModule? _representationModule;
private IContextRepository? _contextRepository; private IContextRepository? _contextRepository;
private IMethodRepository? _methodRepository; private IMethodRepository? _methodRepository;
@@ -85,4 +88,5 @@ public class RequestExtractor : IRequestExtractor
multiClientOwnershipRepository?.RegisterOwnership(_representationModule.Id); 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 class StaticOwnershipRepository : IOwnershipRepository
{
private readonly int _id;
public StaticOwnershipRepository(int id)
{
_id = id;
}
public int GetOwnershipId() public int GetOwnershipId()
{ {
return id; return _id;
} }
public int GetHostOwnershipId() public int GetHostOwnershipId()
{ {
return id; return _id;
}
} }
} }
+4 -3
View File
@@ -1,6 +1,7 @@
namespace mROA.Implementation; namespace mROA.Implementation
public class IdAssingnment
{ {
public class IdAssingnment
{
public int Id { get; set; } public int Id { get; set; }
}
} }
@@ -1,10 +1,11 @@
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 class JsonSerializationToolkit : ISerializationToolkit
{
public byte[] Serialize<T>(T objectToSerialize) public byte[] Serialize<T>(T objectToSerialize)
{ {
return JsonSerializer.SerializeToUtf8Bytes(objectToSerialize); return JsonSerializer.SerializeToUtf8Bytes(objectToSerialize);
@@ -56,4 +57,5 @@ public class JsonSerializationToolkit : ISerializationToolkit
public void Inject<T>(T dependency) public void Inject<T>(T dependency)
{ {
} }
}
} }
+9 -5
View File
@@ -1,12 +1,15 @@
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
{
private readonly List<MethodInfo> _methods = new() { };
public MethodInfo GetMethod(int id) public MethodInfo GetMethod(int id)
{ {
@@ -40,4 +43,5 @@ public class MethodRepository : IMethodRepository
{ {
} }
}
} }
+12 -10
View File
@@ -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
{
public Guid Id { get; set; }
[JsonConverter(typeof(JsonStringEnumConverter))] [JsonConverter(typeof(JsonStringEnumConverter))]
public MessageType SchemaId { get; init; } 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,9 +1,14 @@
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
{ {
public class NextGenerationInteractionModule : INextGenerationInteractionModule
{
private ISerializationToolkit? _serialization; private ISerializationToolkit? _serialization;
public int ConnectionId { get; private set; } public int ConnectionId { get; private set; }
public Stream? BaseStream { get; set; } public Stream? BaseStream { get; set; }
@@ -26,7 +31,6 @@ public class NextGenerationInteractionModule : INextGenerationInteractionModule
} }
} }
public Task<NetworkMessage> GetNextMessageReceiving() public Task<NetworkMessage> GetNextMessageReceiving()
{ {
if (_currentReceiving != null) return _currentReceiving; if (_currentReceiving != null) return _currentReceiving;
@@ -62,7 +66,7 @@ public class NextGenerationInteractionModule : INextGenerationInteractionModule
return _messageBuffer.FirstOrDefault(m => predicate(m)); return _messageBuffer.FirstOrDefault(m => predicate(m));
} }
private NetworkMessage GetNextMessage() private async Task<NetworkMessage> GetNextMessage()
{ {
if (BaseStream == null) if (BaseStream == null)
throw new NullReferenceException("BaseStream is null"); throw new NullReferenceException("BaseStream is null");
@@ -72,16 +76,20 @@ public class NextGenerationInteractionModule : INextGenerationInteractionModule
// Console.WriteLine("Receiving message"); // Console.WriteLine("Receiving message");
var len = BitConverter.ToUInt16([(byte)BaseStream.ReadByte(), (byte)BaseStream.ReadByte()]); var firstBit = (byte)BaseStream.ReadByte();
var localSpan = _buffer.Span.Slice(0, len); var secondBit = (byte)BaseStream.ReadByte();
BaseStream.ReadExactly(localSpan);
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])); // Console.WriteLine("Receiving {0}", Encoding.Default.GetString(_buffer[..len]));
var message = _serialization.Deserialize<NetworkMessage>(localSpan); var message = _serialization.Deserialize<NetworkMessage>(localSpan.Span);
_messageBuffer.Add(message!); _messageBuffer.Add(message!);
_currentReceiving = Task.Run(GetNextMessage); _currentReceiving = GetNextMessage();
return message!; return message!;
} }
}
} }
@@ -1,12 +1,13 @@
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
{ {
public class RemoteContextRepository : IContextRepository
{
private IRepresentationModuleProducer? _representationProducer; private IRepresentationModuleProducer? _representationProducer;
public static FrozenDictionary<Type, Type> RemoteTypes = FrozenDictionary<Type, Type>.Empty; public static Dictionary<Type, Type> RemoteTypes = new();
public int ResisterObject(object o) public int ResisterObject(object o)
{ {
throw new NotSupportedException(); throw new NotSupportedException();
@@ -54,4 +55,5 @@ public class RemoteContextRepository : IContextRepository
if (dependency is IRepresentationModuleProducer serialisationModule) if (dependency is IRepresentationModuleProducer serialisationModule)
_representationProducer = serialisationModule; _representationProducer = serialisationModule;
} }
}
} }
+25 -14
View File
@@ -1,26 +1,36 @@
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; {
private readonly int _id;
private readonly IRepresentationModule _representationModule;
protected RemoteObjectBase(int id, IRepresentationModule representationModule)
{
_id = id;
_representationModule = representationModule;
}
public int Id => _id;
public int OwnerId => _representationModule.Id;
protected async Task<T> GetResultAsync<T>(int methodId, object? parameter = default) protected async Task<T> GetResultAsync<T>(int methodId, object? parameter = default)
{ {
var request = new DefaultCallRequest var request = new DefaultCallRequest
{ CommandId = methodId, ObjectId = id, Parameter = parameter, ParameterType = parameter?.GetType() }; { CommandId = methodId, ObjectId = _id, Parameter = parameter, ParameterType = parameter?.GetType() };
await representationModule.PostCallMessageAsync(request.Id, MessageType.CallRequest, request); await _representationModule.PostCallMessageAsync(request.Id, MessageType.CallRequest, request);
var successResponse = var successResponse =
representationModule.GetMessageAsync<FinalCommandExecution<T>>( _representationModule.GetMessageAsync<FinalCommandExecution<T>>(
messageType: MessageType.FinishedCommandExecution, requestId: request.Id); messageType: MessageType.FinishedCommandExecution, requestId: request.Id);
var errorResponse = var errorResponse =
representationModule.GetMessageAsync<ExceptionCommandExecution>( _representationModule.GetMessageAsync<ExceptionCommandExecution>(
messageType: MessageType.ExceptionCommandExecution, requestId: request.Id); messageType: MessageType.ExceptionCommandExecution, requestId: request.Id);
Task.WaitAny(successResponse, errorResponse); Task.WaitAny(successResponse, errorResponse);
@@ -33,14 +43,14 @@ public abstract class RemoteObjectBase(int id, IRepresentationModule representat
protected async Task CallAsync(int methodId, object? parameter = default) protected async Task CallAsync(int methodId, object? parameter = default)
{ {
var request = new DefaultCallRequest var request = new DefaultCallRequest
{ CommandId = methodId, ObjectId = id, Parameter = parameter, ParameterType = parameter?.GetType() }; { CommandId = methodId, ObjectId = _id, Parameter = parameter, ParameterType = parameter?.GetType() };
await representationModule.PostCallMessageAsync(request.Id, MessageType.CallRequest, request); await _representationModule.PostCallMessageAsync(request.Id, MessageType.CallRequest, request);
var successResponse = var successResponse =
representationModule.GetMessageAsync<FinalCommandExecution>( _representationModule.GetMessageAsync<FinalCommandExecution>(
messageType: MessageType.FinishedCommandExecution, requestId: request.Id); messageType: MessageType.FinishedCommandExecution, requestId: request.Id);
var errorResponse = var errorResponse =
representationModule.GetMessageAsync<ExceptionCommandExecution>( _representationModule.GetMessageAsync<ExceptionCommandExecution>(
messageType: MessageType.ExceptionCommandExecution, requestId: request.Id); messageType: MessageType.ExceptionCommandExecution, requestId: request.Id);
Task.WaitAny(successResponse, errorResponse); Task.WaitAny(successResponse, errorResponse);
@@ -50,4 +60,5 @@ public abstract class RemoteObjectBase(int id, IRepresentationModule representat
throw errorResponse.Result.GetException(); throw errorResponse.Result.GetException();
} }
}
} }
+7 -4
View File
@@ -1,9 +1,11 @@
using mROA.Abstract; using System;
using System.Threading.Tasks;
using mROA.Abstract;
namespace mROA.Implementation; namespace mROA.Implementation
public class RepresentationModule : IRepresentationModule
{ {
public class RepresentationModule : IRepresentationModule
{
private ISerializationToolkit? _serialization; private ISerializationToolkit? _serialization;
private INextGenerationInteractionModule? _interaction; private INextGenerationInteractionModule? _interaction;
@@ -90,4 +92,5 @@ public class RepresentationModule : IRepresentationModule
{ {
PostCallMessageAsync(id, messageType, payload, payloadType).GetAwaiter().GetResult(); PostCallMessageAsync(id, messageType, payload, payloadType).GetAwaiter().GetResult();
} }
}
} }
+12 -10
View File
@@ -1,12 +1,13 @@
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
{ {
public static class TransmissionConfig
{
private static IContextRepository? _realContextRepository; private static IContextRepository? _realContextRepository;
private static IContextRepository? _remoteEndpointContextRepository; private static IContextRepository? _remoteEndpointContextRepository;
private static IOwnershipRepository? _ownershipRepository; private static IOwnershipRepository? _ownershipRepository;
@@ -29,10 +30,10 @@ public static class TransmissionConfig
set => _ownershipRepository = value; set => _ownershipRepository = value;
} }
} }
public class SharedObject<T> where T : notnull public class SharedObject<T> where T : notnull
{ {
private IContextRepository GetDefaultContextRepository() => private IContextRepository GetDefaultContextRepository() =>
(OwnerId == TransmissionConfig.OwnershipRepository.GetHostOwnershipId() (OwnerId == TransmissionConfig.OwnershipRepository.GetHostOwnershipId()
? TransmissionConfig.RealContextRepository ? TransmissionConfig.RealContextRepository
@@ -50,7 +51,7 @@ public class SharedObject<T> where T : notnull
_ownerId = _ownerId == -1 ? TransmissionConfig.OwnershipRepository.GetOwnershipId() : _ownerId; _ownerId = _ownerId == -1 ? TransmissionConfig.OwnershipRepository.GetOwnershipId() : _ownerId;
return _ownerId; return _ownerId;
} }
init => _ownerId = value; set => _ownerId = value;
} }
// ReSharper disable once MemberCanBePrivate.Global // ReSharper disable once MemberCanBePrivate.Global
@@ -65,14 +66,14 @@ public class SharedObject<T> where T : notnull
_contextId = TransmissionConfig.RealContextRepository.GetObjectIndex(Value); _contextId = TransmissionConfig.RealContextRepository.GetObjectIndex(Value);
return _contextId; return _contextId;
} }
init set
{ {
_contextId = value; _contextId = value;
Value = GetDefaultContextRepository().GetObject<T>(_contextId)!; Value = GetDefaultContextRepository().GetObject<T>(_contextId)!;
} }
} }
[JsonIgnore] public T Value { get; private init; } [JsonIgnore] public T Value { get; private set; }
// ReSharper disable once MemberCanBePrivate.Global // ReSharper disable once MemberCanBePrivate.Global
// ReSharper disable once UnusedMember.Global // ReSharper disable once UnusedMember.Global
@@ -98,4 +99,5 @@ public class SharedObject<T> where T : notnull
public static implicit operator SharedObject<T>(T value) => public static implicit operator SharedObject<T>(T value) =>
new(value); new(value);
}
} }
@@ -1,9 +1,10 @@
using mROA.Abstract; using System;
using mROA.Abstract;
namespace mROA.Implementation; namespace mROA.Implementation
public class StaticRepresentationModuleProducer : IRepresentationModuleProducer
{ {
public class StaticRepresentationModuleProducer : IRepresentationModuleProducer
{
private IRepresentationModule? _representationModule; private IRepresentationModule? _representationModule;
public IRepresentationModule Produce(int ownership) public IRepresentationModule Produce(int ownership)
@@ -18,4 +19,5 @@ public class StaticRepresentationModuleProducer : IRepresentationModuleProducer
if (dependency is IRepresentationModule serialisationModule) if (dependency is IRepresentationModule serialisationModule)
_representationModule = serialisationModule; _representationModule = serialisationModule;
} }
}
} }
+43
View File
@@ -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
View File
@@ -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>