перевод на передачу с обозначением схемы

This commit is contained in:
2025-02-12 12:34:54 +03:00
parent 318484025d
commit 5032fa28e8
18 changed files with 143 additions and 62 deletions
+15
View File
@@ -11,4 +11,19 @@ public class LoadTestImp : ILoadTest
{
return last + 1;
}
public int Last(int next)
{
return next - 1;
}
public void C()
{
throw new NotImplementedException();
}
public void A()
{
throw new NotImplementedException();
}
}
+1 -1
View File
@@ -8,7 +8,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Example.Shared\Example.Shared.csproj" />
<ProjectReference Include="..\Example.Shared\Example.Shared.csproj" />
</ItemGroup>
</Project>
+1 -1
View File
@@ -16,7 +16,6 @@ mixer.Modules.Add(new FrontendContextRepository());
mixer.Modules.Add(new JsonFrontendSerialisationModule());
mixer.Modules.Add(new StreamBasedFrontendInteractionModule());
mixer.Modules.Add(new NetworkFrontendBridge(new IPEndPoint(IPAddress.Loopback, 4567)));
mixer.Build();
mixer.GetModule<NetworkFrontendBridge>().Connect();
@@ -25,6 +24,7 @@ var context = mixer.GetModule<FrontendContextRepository>();
var factory = context.GetSingleObject(typeof(IPrinterFactory)) as IPrinterFactory;
var printer = factory.Create("Test");
var name = printer.Value.GetName();
Console.WriteLine("Printer name : {0}", name);
+2 -1
View File
@@ -7,8 +7,9 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\mROA.Codegen\mROA.Codegen.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false"/>
<ProjectReference Include="..\mROA\mROA.csproj"/>
<ProjectReference Include="..\mROA.Codegen\mROA.Codegen.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false"/>
</ItemGroup>
</Project>
+3
View File
@@ -7,4 +7,7 @@ namespace Example.Shared;
public interface ILoadTest
{
int Next(int last);
int Last(int next);
void C();
void A();
}
+7 -7
View File
@@ -77,14 +77,15 @@ namespace {Namespace}
/// </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="classDeclarations">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,
ImmutableArray<InterfaceDeclarationSyntax> classDeclarations)
ImmutableArray<InterfaceDeclarationSyntax> classes)
{
var methods = new List<(string, IMethodSymbol)>();
var frontendContextRepo = new List<string>();
// Go through all filtered class declarations.
foreach (var classDeclarationSyntax in classDeclarations)
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);
@@ -102,7 +103,7 @@ namespace {Namespace}
// Go through all class members with a particular type (property) to generate method lines.
var methodBody = classSymbol.GetMembers()
.OfType<IMethodSymbol>();
.OfType<IMethodSymbol>().OrderBy(i => i.Name);
var originalName = className;
// Build up the source code
@@ -212,10 +213,10 @@ using mROA.Abstract;
namespace mROA.Codegen;
public class CoCodegenMethodRepository :IMethodRepository
public class CoCodegenMethodRepository : IMethodRepository
{{
private readonly List<MethodInfo> _methods = [
{string.Join(", \r\n\t\t", methodsStringed)}
{string.Join(", // test comment\r\n\t\t", methodsStringed)}
];
public MethodInfo GetMethod(int id)
{{
@@ -310,6 +311,5 @@ public class FrontendContextRepository : IContextRepository
";
context.AddSource("FrontendContextRepository.g.cs", SourceText.From(fronendRepoCode, Encoding.UTF8));
}
}
}
+1 -1
View File
@@ -3,7 +3,7 @@ namespace mROA.Abstract;
public interface IInteractionModule : IInjectableModule
{
void SendTo(int clientId, byte[] message);
void RegisterSourse(Stream stream);
void RegisterSource(Stream stream);
public interface IFrontendInteractionModule : IInjectableModule
{
public Task<byte[]> ReceiveMessage();
+2 -2
View File
@@ -4,8 +4,8 @@ namespace mROA.Abstract;
public interface ISerialisationModule : IInjectableModule
{
void HandleIncomingRequest(int clientId, byte[] command);
void PostResponse(ICommandExecution call);
void HandleIncomingRequest(int clientId, byte[] message);
void PostResponse(NetworkMessage message, int clientId);
public interface IFrontendSerialisationModule : IInjectableModule
{
Task<T> GetNextCommandExecution<T>(Guid requestId) where T : ICommandExecution;
@@ -1,4 +1,5 @@
using System.Text;
using System.Net.Sockets;
using System.Text;
using System.Text.Json;
using mROA.Abstract;
@@ -10,26 +11,39 @@ public class JsonSerialisationModule : ISerialisationModule
private IExecuteModule? _executeModule;
private IMethodRepository? _methodRepository;
public void HandleIncomingRequest(int clientId, byte[] command)
public void HandleIncomingRequest(int clientId, byte[] message)
{
DefaultCallRequest request = JsonSerializer.Deserialize<DefaultCallRequest>(command)!;
NetworkMessage input = JsonSerializer.Deserialize<NetworkMessage>(message)!;
if (request.Parameter is not null)
if (input.SchemaId == MessageType.CallRequest)
{
var parameter = _methodRepository!.GetMethod(request.CommandId).GetParameters().First().ParameterType;
request.Parameter = ((JsonElement)request.Parameter).Deserialize(parameter);
}
var command = JsonSerializer.Deserialize<DefaultCallRequest>(input.Data);
if (command.Parameter is not null)
{
var parameter = _methodRepository!.GetMethod(command.CommandId).GetParameters().First().ParameterType;
command.Parameter = ((JsonElement)command.Parameter).Deserialize(parameter);
}
var response = _executeModule!.Execute(request);
response.ClientId = clientId;
PostResponse(response);
var response = _executeModule!.Execute(command);
response.ClientId = clientId;
var resultType = response is FinalCommandExecution
? MessageType.FinishedCommandExecution
: MessageType.ErrorCommandExecution;
PostResponse(
new NetworkMessage
{
SchemaId = resultType,
Id = command.CallRequestId,
Data = JsonSerializer.SerializeToUtf8Bytes(response, response.GetType())
}, clientId);
}
}
public void PostResponse(ICommandExecution call)
public void PostResponse(NetworkMessage message, int clientId)
{
var texted = JsonSerializer.Serialize(call, call.GetType());
var texted = JsonSerializer.Serialize(message);
var binary = Encoding.UTF8.GetBytes(texted);
_dataSource!.SendTo(call.ClientId, binary);
_dataSource!.SendTo(clientId, binary);
}
public void Inject<T>(T dependency)
@@ -41,5 +55,4 @@ public class JsonSerialisationModule : ISerialisationModule
if (dependency is IMethodRepository methodRepository)
_methodRepository = methodRepository;
}
}
@@ -45,7 +45,7 @@ public class NetworkGatewayModule(IPEndPoint endpoint) : IGatewayModule
{
var client = _tcpListener.AcceptTcpClient();
Console.WriteLine($"Client connected from {client.Client.RemoteEndPoint}");
_interactionModule.RegisterSourse(client.GetStream());
_interactionModule.RegisterSource(client.GetStream());
Console.WriteLine("Client registered");
}
}
@@ -7,7 +7,7 @@ public class StreamBasedInteractionModule : IInteractionModule
private readonly Dictionary<int, Stream> _streams = new();
private Action<int, byte[]>? _handler;
public void RegisterSourse(Stream stream)
public void RegisterSource(Stream stream)
{
var id = Random.Shared.Next();
_streams.Add(id, stream);
@@ -0,0 +1,11 @@
using mROA.Abstract;
namespace mROA.Implementation;
public class ExceptionCommandExecution : ICommandExecution
{
public Guid CallRequestId { get; init; }
public int ClientId { get; set; }
public int CommandId { get; init; }
public required string Exception { get; set; }
}
@@ -18,17 +18,3 @@ public class FinalCommandExecution<T> : FinalCommandExecution
{
public T? Result { get; init; }
}
public class TypedFinalCommandExecution : FinalCommandExecution<object>
{
[JsonIgnore]
public Type? Type { get; set; }
}
public class ExceptionCommandExecution : ICommandExecution
{
public Guid CallRequestId { get; init; }
public int ClientId { get; set; }
public int CommandId { get; init; }
public required string Exception { get; set; }
}
@@ -0,0 +1,9 @@
using System.Text.Json.Serialization;
namespace mROA.Implementation;
public class TypedFinalCommandExecution : FinalCommandExecution<object>
{
[JsonIgnore]
public Type? Type { get; set; }
}
@@ -0,0 +1,24 @@
using mROA.Abstract;
namespace mROA.Implementation.Frontend;
public class JsonFrontendCallbackSerializationModule : ISerialisationModule
{
private IInteractionModule.IFrontendInteractionModule? _interactionModule;
public void Inject<T>(T dependency)
{
if (dependency is IInteractionModule.IFrontendInteractionModule interactionModule)
_interactionModule = interactionModule;
}
public void HandleIncomingRequest(int clientId, byte[] message)
{
}
public void PostResponse(NetworkMessage message, int clientId)
{
throw new NotImplementedException();
}
}
@@ -31,21 +31,21 @@ public class JsonFrontendSerialisationModule
throw new Exception("Interaction module not initialized");
var receiveMessage = await _interactionModule.ReceiveMessage();
// var str = Encoding.UTF8.GetString(receiveMessage);
var document = JsonDocument.Parse(receiveMessage);
if (document.RootElement.TryGetProperty("Exception", out var exceptionElement))
{
throw new RemoteException(exceptionElement.GetString()!) { CallRequestId = requestId };
}
var parsed = document.Deserialize<FinalCommandExecution<T>>()!;
while (parsed.CallRequestId != requestId)
var message = JsonSerializer.Deserialize<NetworkMessage>(receiveMessage)!;
while (message.Id != requestId)
{
receiveMessage = await _interactionModule.ReceiveMessage();
parsed = JsonSerializer.Deserialize<FinalCommandExecution<T>>(receiveMessage)!;
message = JsonSerializer.Deserialize<NetworkMessage>(receiveMessage)!;
}
return parsed;
if (message.SchemaId == MessageType.ErrorCommandExecution)
{
throw new RemoteException(JsonSerializer.Deserialize<ExceptionCommandExecution>(message.Data)!.Exception)
{ CallRequestId = requestId };
}
return JsonSerializer.Deserialize<FinalCommandExecution<T>>(message.Data)!;
}
public void PostCallRequest(ICallRequest callRequest)
@@ -53,8 +53,13 @@ public class JsonFrontendSerialisationModule
if (_interactionModule is null)
throw new Exception("Interaction module not initialized");
var post = JsonSerializer.Serialize(callRequest, callRequest.GetType());
_interactionModule.PostMessage(Encoding.UTF8.GetBytes(post));
var post = JsonSerializer.SerializeToUtf8Bytes(callRequest, callRequest.GetType());
_interactionModule.PostMessage(JsonSerializer.SerializeToUtf8Bytes(new NetworkMessage
{
Id = callRequest.CallRequestId,
Data = post,
SchemaId = MessageType.CallRequest
}));
}
public void Inject<T>(T dependency)
@@ -62,7 +67,6 @@ public class JsonFrontendSerialisationModule
if (dependency is IInteractionModule.IFrontendInteractionModule interactionModule)
_interactionModule = interactionModule;
}
}
public class RemoteException(string error) : Exception
+15
View File
@@ -0,0 +1,15 @@
using mROA.Abstract;
namespace mROA.Implementation;
public class NetworkMessage
{
public Guid Id { get; set; }
public MessageType SchemaId { get; set; }
public byte[] Data { get; set; }
}
public enum MessageType
{
Unknown, FinishedCommandExecution, ErrorCommandExecution, AcyncCancelCommandExecution, CallRequest
}
+1 -1
View File
@@ -5,7 +5,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Title>mROA</Title>
<Version>1.1.3</Version>
<Version>2.0.0</Version>
<Authors>YaslePoy</Authors>
<Description>Fast and easy RPC with contex</Description>
<RepositoryUrl>https://github.com/YaslePoy/mROA</RepositoryUrl>