База для нового бэкэнда

This commit is contained in:
2025-03-06 14:10:52 +03:00
parent be6dedaee4
commit c802f337c7
18 changed files with 245 additions and 163 deletions
+18
View File
@@ -0,0 +1,18 @@
using System;
using Example.Shared;
namespace Example.Backend
{
public class CsTest
{
public T FinalCasted<T>(IDataList<T> list, int index)
{
return list.Get(index);
}
public object NonCasted(object list, int index)
{
return FinalCasted(list as IDataList<object>, index);
}
}
}
+24
View File
@@ -0,0 +1,24 @@
using System.Collections.Generic;
using Example.Shared;
namespace Example.Backend
{
public class PagesList : IPagesList
{
public IReadOnlyList<IPage> Collection { get; }
public IPage Get(int index)
{
throw new System.NotImplementedException();
}
public void Add(IPage item)
{
throw new System.NotImplementedException();
}
public void Set(int index, IPage item)
{
throw new System.NotImplementedException();
}
}
}
+2
View File
@@ -1,5 +1,6 @@
using System.Net; using System.Net;
using Example.Backend; using Example.Backend;
using Example.Shared;
using mROA.Abstract; using mROA.Abstract;
using mROA.Cbor; using mROA.Cbor;
using mROA.Codegen; using mROA.Codegen;
@@ -48,5 +49,6 @@ class Program
var gateway = builder.GetModule<IGatewayModule>(); var gateway = builder.GetModule<IGatewayModule>();
gateway.Run(); gateway.Run();
} }
} }
+1
View File
@@ -11,6 +11,7 @@ namespace Example.Frontend
public string GetName() public string GetName()
{ {
Console.WriteLine("ClientBasedPrinter called from server!!!!!!!!!!! Vova likes that:)"); Console.WriteLine("ClientBasedPrinter called from server!!!!!!!!!!! Vova likes that:)");
return "ClientBasedPrinter from mroa"; return "ClientBasedPrinter from mroa";
} }
+3 -1
View File
@@ -17,7 +17,7 @@ class Program
public static void Main(string[] args) public static void Main(string[] args)
{ {
var builder = new FullMixBuilder(); var builder = new FullMixBuilder();
new RemoteTypeBinder(); // new RemoteTypeBinder();
// builder.Modules.Add(new JsonSerializationToolkit()); // builder.Modules.Add(new JsonSerializationToolkit());
builder.Modules.Add(new CborSerializationToolkit()); builder.Modules.Add(new CborSerializationToolkit());
@@ -106,5 +106,7 @@ class Program
// 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");
} }
} }
+10 -7
View File
@@ -1,12 +1,15 @@
using System;
using System.Collections.Generic;
using mROA.Implementation;
using mROA.Implementation.Attributes; using mROA.Implementation.Attributes;
namespace Example.Shared namespace Example.Shared
{ {
// [SharedObjectInterface] public interface IDataList<T> : IShared, IDisposable
// public interface IDataList<T> : IShared {
// { IReadOnlyList<T> Collection { get; }
// T Get(int index); T Get(int index);
// void Add(T item); void Add(T item);
// void Set(int index, T item); void Set(int index, T item);
// } }
} }
+9
View File
@@ -0,0 +1,9 @@
using mROA.Implementation.Attributes;
namespace Example.Shared
{
[SharedObjectInterface]
public interface IPagesList : IDataList<IPage>
{
}
}
+4 -1
View File
@@ -52,8 +52,11 @@ namespace mROA.Cbor
return (T)Cast(nonCasted, typeof(T), context); return (T)Cast(nonCasted, typeof(T), context);
} }
public object Cast(object nonCasted, Type type, IEndPointContext? context) public object? Cast(object? nonCasted, Type type, IEndPointContext? context)
{ {
if (nonCasted == null)
return null;
if (nonCasted.GetType() == type) if (nonCasted.GetType() == type)
return nonCasted; return nonCasted;
+48 -61
View File
@@ -17,74 +17,57 @@ namespace mROA.Codegen
[Generator] [Generator]
public class mROASourceGenerator : ISourceGenerator public class mROASourceGenerator : ISourceGenerator
{ {
private const string Namespace = "mROA.Implementation";
private const string AttributeName = "SharedObjectInterafceAttribute";
private const string AttributeSourceCode = $@"// <auto-generated/>
namespace {Namespace}
{{
[System.AttributeUsage(System.AttributeTargets.Class)]
public class {AttributeName} : System.Attribute
{{
}}
}}";
/// <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(GeneratorExecutionContext 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)>();
var frontendContextRepo = new List<string>(); var frontendContextRepo = new List<string>();
// Go through all filtered class declarations.
var declarations = classes.ToList().OrderBy(i => i.Identifier.Text).ToList(); var declarations = classes.ToList().OrderBy(i => i.Identifier.Text).ToList();
foreach (var classDeclarationSyntax in declarations) foreach (var classDeclarationSyntax in declarations)
{ {
// We need to get semantic model of the class to retrieve metadata.
var semanticModel = compilation.GetSemanticModel(classDeclarationSyntax.SyntaxTree); var semanticModel = compilation.GetSemanticModel(classDeclarationSyntax.SyntaxTree);
// Symbols allow us to get the compile-time information.
if (semanticModel.GetDeclaredSymbol(classDeclarationSyntax) is not INamedTypeSymbol classSymbol) if (semanticModel.GetDeclaredSymbol(classDeclarationSyntax) is not INamedTypeSymbol classSymbol)
continue; continue;
var namespaceName = classSymbol.ContainingNamespace.ToDisplayString(); var namespaceName = classSymbol.ContainingNamespace.ToDisplayString();
// 'Identifier' means the token of the node. Get class name from the syntax node.
var className = classDeclarationSyntax.Identifier.Text; var className = classDeclarationSyntax.Identifier.Text;
var methodBody = CollectMethods(classSymbol);
// 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; var originalName = className;
// Build up the source code
className = className.TrimStart('I') + "RemoteEndpoint"; className = className.TrimStart('I') + "RemoteEndpoint";
var methodsText = new List<string>(); var methodsText = new List<string>();
foreach (var method in methodBody) foreach (var method in methodBody)
{ {
var index = methods.Count; var index = methods.Count;
methods.Add((namespaceName + "." + originalName, method)); methods.Add((namespaceName + "." + originalName, method));
var sb = new StringBuilder(); var sb = new StringBuilder();
bool isParametrized;
bool isAsync = method.ReturnType.Name == "Task"; bool isAsync;
bool isVoid = method.ReturnType.Name == "Void" || bool isVoid;
method.ReturnType.ToString() == "System.Threading.Tasks.Task";
bool isParametrized = method.Parameters.Length == 1 && !isAsync ||
method.Parameters.Length == 2 && isAsync;
switch (method.ReturnType)
{
case INamedTypeSymbol namedType:
isAsync = namedType.Name == "Task";
isVoid = isAsync && namedType.TypeParameters.Length == 0 || namedType.Name == "Void";
isParametrized = method.Parameters.Length == 1 && !isAsync ||
method.Parameters.Length == 2 && isAsync;
break;
case IArrayTypeSymbol:
isAsync = false;
isVoid = false;
isParametrized = method.Parameters.Length != 0;
break;
default:
continue;
}
//Creating signature //Creating signature
sb.AppendLine("public" + (isAsync sb.AppendLine("public" + (isAsync
@@ -140,7 +123,7 @@ namespace {namespaceName}
// 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));
frontendContextRepo.Add( frontendContextRepo.Add(
$"{{ typeof({classSymbol.ToDisplayString()}), typeof({namespaceName}.{className}) }}"); $"{{ typeof({classSymbol.ToDisplayString()}), typeof({namespaceName}.{className}) }}");
@@ -148,31 +131,27 @@ namespace {namespaceName}
if (methods.Count != 0) if (methods.Count != 0)
{ {
// var methodsStringed = methods.Select(i => var methodsStringed = Array.Empty<string>();
// $"typeof({i.Item1}).GetMethod(\"{i.Item2.Name}\", new Type[] {{{string.Join(", ", i.Item2.Parameters.Select(p => $"typeof({p.Type.ToDisplayString()})"))}}})")
// .ToList();
var methodsStringed = methods.Select(i =>
$"typeof({i.Item1}).GetMethod(\"{i.Item2.Name}\")")
.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 mROA.Implementation;
using System; using System;
namespace mROA.Codegen namespace mROA.Codegen
{{ {{
public class CoCodegenMethodRepository : IMethodRepository public class CoCodegenMethodRepository : IMethodRepository
{{ {{
private readonly List<MethodInfo> _methods = new () {{ private readonly List<IMethodInvoker> _methods = new () {{
{string.Join(",\r\n\t\t\t", methodsStringed)} {string.Join(",\r\n\t\t\t", methodsStringed)}
}}; }};
public MethodInfo GetMethod(int id) public IMethodInvoker GetMethod(int id)
{{ {{
if (id == -1) if (id == -1)
return typeof(IDisposable).GetMethod(""Dispose""); return mROA.Implementation.MethodInvoker.Dispose;
if (_methods.Count <= id) if (_methods.Count <= id)
return null; return null;
@@ -186,7 +165,7 @@ namespace mROA.Codegen
}} }}
}} }}
"; ";
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)
@@ -209,7 +188,7 @@ namespace mROA.Codegen
}} }}
}} }}
"; ";
context.AddSource("RemoteTypeBinder.g.cs", SourceText.From(fronendRepoCode, Encoding.UTF8)); // context.AddSource("RemoteTypeBinder.g.cs", SourceText.From(fronendRepoCode, Encoding.UTF8));
} }
} }
@@ -225,9 +204,7 @@ namespace mROA.Codegen
private string ExtractTaskType(ITypeSymbol taskType) private string ExtractTaskType(ITypeSymbol taskType)
{ {
var type = taskType.ToString(); return (taskType as INamedTypeSymbol).TypeParameters[0].ToDisplayString();
type = type.Substring(type.IndexOf('<') + 1);
return type.Substring(0, type.Length - 1);
} }
public void Initialize(GeneratorInitializationContext context) public void Initialize(GeneratorInitializationContext context)
@@ -266,8 +243,7 @@ namespace mROA.Codegen
private bool ContainsSOIAttribute(SyntaxList<AttributeListSyntax> attributes, GeneratorExecutionContext context, private bool ContainsSOIAttribute(SyntaxList<AttributeListSyntax> attributes, GeneratorExecutionContext context,
InterfaceDeclarationSyntax interfaceDeclarationSyntax) InterfaceDeclarationSyntax interfaceDeclarationSyntax)
{ {
foreach (AttributeListSyntax attributeListSyntax in attributes) foreach (var attributeSyntax in attributes.SelectMany(attributeListSyntax => attributeListSyntax.Attributes))
foreach (AttributeSyntax attributeSyntax in attributeListSyntax.Attributes)
{ {
if (context.Compilation.GetSemanticModel(interfaceDeclarationSyntax.SyntaxTree) if (context.Compilation.GetSemanticModel(interfaceDeclarationSyntax.SyntaxTree)
.GetSymbolInfo(attributeSyntax).Symbol is not IMethodSymbol attributeSymbol) .GetSymbolInfo(attributeSyntax).Symbol is not IMethodSymbol attributeSymbol)
@@ -282,5 +258,16 @@ namespace mROA.Codegen
return false; return false;
} }
private List<IMethodSymbol> CollectMethods(INamedTypeSymbol type)
{
var methods = type.GetMembers().OfType<IMethodSymbol>().ToList();
foreach (var inner in type.AllInterfaces)
{
methods.AddRange(inner.GetMembers().OfType<IMethodSymbol>());
}
return methods.OrderBy(i => i.Name).ToList();
}
} }
} }
+2 -1
View File
@@ -8,6 +8,7 @@ namespace mROA.Abstract
bool IsVoid { get; } bool IsVoid { get; }
Type[] ParameterTypes { get; } Type[] ParameterTypes { get; }
Type? ReturnType { get; } Type? ReturnType { get; }
object? Invoke(object instance, object?[] parameters, object[] special); object? Invoke(object instance, object?[]? parameters, object[] special);
Type SuitableType { get; }
} }
} }
+1 -1
View File
@@ -4,6 +4,6 @@ namespace mROA.Abstract
{ {
public interface IMethodRepository : IInjectableModule public interface IMethodRepository : IInjectableModule
{ {
MethodInfo GetMethod(int id); IMethodInvoker GetMethod(int id);
} }
} }
+2 -2
View File
@@ -10,8 +10,8 @@ namespace mROA.Abstract
object? Deserialize(byte[] rawData, Type type); object? Deserialize(byte[] rawData, Type type);
T? Deserialize<T>(Span<byte> rawData); T? Deserialize<T>(Span<byte> rawData);
object? Deserialize(Span<byte> rawData, Type type); object? Deserialize(Span<byte> rawData, Type type);
T? Cast<T>(object nonCasted); T? Cast<T>(object? nonCasted);
object? Cast(object nonCasted, Type type); object? Cast(object? nonCasted, Type type);
} }
} }
@@ -1,4 +1,5 @@
using System; using System;
using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -11,11 +12,22 @@ namespace mROA.Implementation.Backend
{ {
private IMethodRepository? _methodRepo; private IMethodRepository? _methodRepo;
private ICancellationRepository? _cancellationRepo; private ICancellationRepository? _cancellationRepo;
private ISerializationToolkit? _serialization;
public void Inject<T>(T dependency) public void Inject<T>(T dependency)
{ {
if (dependency is IMethodRepository methodRepo) _methodRepo = methodRepo; switch (dependency)
if (dependency is ICancellationRepository cancellationRepo) _cancellationRepo = cancellationRepo; {
case IMethodRepository methodRepo:
_methodRepo = methodRepo;
break;
case ICancellationRepository cancellationRepo:
_cancellationRepo = cancellationRepo;
break;
case ISerializationToolkit serializationToolkit:
_serialization = serializationToolkit;
break;
}
} }
public ICommandExecution Execute(ICallRequest command, IContextRepository contextRepository, public ICommandExecution Execute(ICallRequest command, IContextRepository contextRepository,
@@ -24,50 +36,69 @@ namespace mROA.Implementation.Backend
#if TRACE #if TRACE
Console.WriteLine(command.GetType().Name); Console.WriteLine(command.GetType().Name);
#endif #endif
if (_cancellationRepo is null)
throw new NullReferenceException("Method repository was not defined");
if (_methodRepo is null)
throw new NullReferenceException("Method repository was not defined");
if (contextRepository is null)
throw new NullReferenceException("Context repository was not defined");
if (command is CancelRequest)
{
#if TRACE
Console.WriteLine("Final cancelling request");
#endif
var cts = _cancellationRepo.GetCancellation(command.Id);
cts.Cancel();
_cancellationRepo.FreeCancelation(command.Id);
return new FinalCommandExecution
{
Id = command.Id
};
}
var currentCommand = _methodRepo.GetMethod(command.CommandId);
if (currentCommand == null)
throw new Exception($"Command {command.CommandId} not found");
var context = command.ObjectId != -1
? contextRepository.GetObject<object>(command.ObjectId)
: contextRepository.GetSingleObject(currentCommand.DeclaringType!);
var parameter = command.Parameter;
if (currentCommand.ReturnType.BaseType == typeof(Task) &&
currentCommand.ReturnType.GenericTypeArguments.Length == 1)
return TypedExecuteAsync(currentCommand, context, parameter, command, _cancellationRepo,
representationModule);
if (currentCommand.ReturnType == typeof(Task))
return ExecuteAsync(currentCommand, context, parameter, command, _cancellationRepo,
representationModule);
try try
{ {
var result = Execute(currentCommand, context, parameter, command); if (_cancellationRepo is null)
throw new NullReferenceException("Method repository was not defined");
if (_methodRepo is null)
throw new NullReferenceException("Method repository was not defined");
if (contextRepository is null)
throw new NullReferenceException("Context repository was not defined");
if (command is CancelRequest)
{
#if TRACE
Console.WriteLine("Final cancelling request");
#endif
var cts = _cancellationRepo.GetCancellation(command.Id);
if (cts == null)
throw new NullReferenceException("Can't find cancellation for this request");
cts.Cancel();
_cancellationRepo.FreeCancelation(command.Id);
return new FinalCommandExecution
{
Id = command.Id
};
}
var invoker = _methodRepo.GetMethod(command.CommandId);
if (invoker == null)
throw new Exception($"Command {command.CommandId} not found");
var context = command.ObjectId != -1
? contextRepository.GetObject<object>(command.ObjectId)
: contextRepository.GetSingleObject(invoker.SuitableType);
if (context == null)
throw new NullReferenceException("Instance can't be null");
object?[]? castedParams = null;
if (invoker.ParameterTypes != Type.EmptyTypes)
{
castedParams = new object[invoker.ParameterTypes.Length];
for (int i = 0; i < castedParams.Length; i++)
{
castedParams[i] = _serialization.Cast(command.Parameters![i], invoker.ParameterTypes[i]);
}
}
var execContext = new RequestContext(command.Id, representationModule.Id);
if (invoker is { IsAsync: true, IsVoid: false })
return TypedExecuteAsync(invoker, context, castedParams, command, _cancellationRepo,
representationModule, execContext);
if (invoker.IsAsync)
return ExecuteAsync(invoker, context, castedParams, command, _cancellationRepo,
representationModule, execContext);
var result = Execute(invoker, context, castedParams, command, execContext);
if (command.CommandId == -1) if (command.CommandId == -1)
{ {
#if TRACE #if TRACE
@@ -80,23 +111,22 @@ namespace mROA.Implementation.Backend
} }
catch (Exception e) catch (Exception e)
{ {
Console.WriteLine(e); return new ExceptionCommandExecution
throw; {
Id = command.Id,
Exception = e.ToString()
};
} }
} }
private static ICommandExecution Execute(MethodInfo currentCommand, object context, object? parameter, private static ICommandExecution Execute(IMethodInvoker invoker, object instance, object?[] parameter,
ICallRequest command) ICallRequest command, RequestContext executionContext)
{ {
try try
{ {
var finalParameter = parameter is null var finalResult = invoker.Invoke(instance, parameter, new object[] { executionContext });
? Array.Empty<object>()
: new[]
{ parameter };
var finalResult = currentCommand.Invoke(context, finalParameter);
if (currentCommand.ReturnType.Name == "Void") if (invoker.IsVoid)
{ {
return new FinalCommandExecution return new FinalCommandExecution
{ {
@@ -120,9 +150,9 @@ namespace mROA.Implementation.Backend
} }
} }
private ICommandExecution ExecuteAsync(MethodInfo currentCommand, object context, object? parameter, private ICommandExecution ExecuteAsync(IMethodInvoker invoker, object instance, object?[]? parameters,
ICallRequest command, ICancellationRepository cancellationRepository, ICallRequest command, ICancellationRepository cancellationRepository,
IRepresentationModule representationModule) IRepresentationModule representationModule, RequestContext executionContext)
{ {
var tokenSource = new CancellationTokenSource(); var tokenSource = new CancellationTokenSource();
cancellationRepository.RegisterCancellation(command.Id, tokenSource); cancellationRepository.RegisterCancellation(command.Id, tokenSource);
@@ -132,11 +162,7 @@ namespace mROA.Implementation.Backend
#endif #endif
try try
{ {
var finalParameter = parameter is null var result = (Task)invoker.Invoke(instance, parameters, new object[] { executionContext, token })!;
? new object[] { token }
: new[]
{ parameter, token };
var result = (Task)currentCommand.Invoke(context, finalParameter)!;
result.ContinueWith(_ => result.ContinueWith(_ =>
@@ -173,9 +199,9 @@ namespace mROA.Implementation.Backend
} }
} }
private ICommandExecution TypedExecuteAsync(MethodInfo currentCommand, object context, object? parameter, private ICommandExecution TypedExecuteAsync(IMethodInvoker invoker, object instance, object?[]? parameters,
ICallRequest command, ICancellationRepository cancellationRepository, ICallRequest command, ICancellationRepository cancellationRepository,
IRepresentationModule representationModule) IRepresentationModule representationModule, RequestContext executionContext)
{ {
var tokenSource = new CancellationTokenSource(); var tokenSource = new CancellationTokenSource();
cancellationRepository.RegisterCancellation(command.Id, tokenSource); cancellationRepository.RegisterCancellation(command.Id, tokenSource);
@@ -183,12 +209,8 @@ namespace mROA.Implementation.Backend
var token = tokenSource.Token; var token = tokenSource.Token;
try try
{ {
var finalParameter = parameter is null
? new object[] { token }
: new[]
{ parameter, token };
var result = var result =
(Task)currentCommand.Invoke(context, finalParameter)!; (Task)invoker.Invoke(instance, parameters, new object[] { executionContext, token })!;
result.ContinueWith(t => result.ContinueWith(t =>
{ {
@@ -198,7 +220,7 @@ namespace mROA.Implementation.Backend
Id = command.Id, Id = command.Id,
Result = finalResult Result = finalResult
}; };
_cancellationRepo.FreeCancelation(command.Id); _cancellationRepo!.FreeCancelation(command.Id);
var multiClientOwnershipRepository = var multiClientOwnershipRepository =
TransmissionConfig.OwnershipRepository as MultiClientOwnershipRepository; TransmissionConfig.OwnershipRepository as MultiClientOwnershipRepository;
+3 -3
View File
@@ -11,7 +11,7 @@ namespace mROA.Implementation
Guid Id { get; } Guid Id { get; }
int CommandId { get; } int CommandId { get; }
int ObjectId { get; } int ObjectId { get; }
object? Parameter { get; } object?[]? Parameters { get; }
} }
public class DefaultCallRequest : ICallRequest public class DefaultCallRequest : ICallRequest
@@ -20,7 +20,7 @@ namespace mROA.Implementation
public int CommandId { get; set; } public int CommandId { get; set; }
public int ObjectId { get; set; } = -1; public int ObjectId { get; set; } = -1;
public object? Parameter { get; set; } public object?[]? Parameters { get; set; }
public override string ToString() public override string ToString()
{ {
return $"Call request {{ Id : {Id}, CommandId : {CommandId}, ObjectId : {ObjectId} }}"; return $"Call request {{ Id : {Id}, CommandId : {CommandId}, ObjectId : {ObjectId} }}";
@@ -32,7 +32,7 @@ namespace mROA.Implementation
public Guid Id { get; set; } public Guid Id { get; set; }
public int CommandId { get; set; } = -2; public int CommandId { get; set; } = -2;
public int ObjectId { get; set; } = -2; public int ObjectId { get; set; } = -2;
public object? Parameter { get; set; } = null; public object?[]? Parameters { get; set; } = null;
public override string ToString() public override string ToString()
{ {
return $"Cancel request {{ Id : {Id}, CommandId : {CommandId}, ObjectId : {ObjectId} }}"; return $"Cancel request {{ Id : {Id}, CommandId : {CommandId}, ObjectId : {ObjectId} }}";
@@ -94,15 +94,6 @@ namespace mROA.Implementation.Frontend
tokenSource.Cancel(); tokenSource.Cancel();
var request = defaultRequest.Result; var request = defaultRequest.Result;
if (request.Parameter is not null)
{
var method = _methodRepository!.GetMethod(request.CommandId);
var parameterType = method.GetParameters().First()
.ParameterType;
request.Parameter = _serializationToolkit.Cast(request.Parameter, parameterType);
}
var result = _executeModule.Execute(request, _contextRepository, _representationModule); var result = _executeModule.Execute(request, _contextRepository, _representationModule);
var resultType = MessageType.Unknown; var resultType = MessageType.Unknown;
+8 -5
View File
@@ -9,23 +9,26 @@ namespace mROA.Implementation
public bool IsVoid { get; set; } public bool IsVoid { get; set; }
public Type[] ParameterTypes { get; set; } = Type.EmptyTypes; public Type[] ParameterTypes { get; set; } = Type.EmptyTypes;
public Type? ReturnType { get; set; } public Type? ReturnType { get; set; }
public Func<object, object?[], object[], object?> Invoking { get; set; } public Func<object, object?[]?, object[], object?> Invoking { get; set; } = (_, _, _) => null;
public object? Invoke(object instance, object?[] parameters, object[] special) public object? Invoke(object instance, object?[]? parameters, object[] special)
{ {
return Invoking(instance, parameters, special); return Invoking(instance, parameters, special);
} }
public static MethodInvoker Dispose = new MethodInvoker public Type SuitableType { get; set; } = null!;
public static readonly IMethodInvoker Dispose = new MethodInvoker
{ {
IsAsync = false, IsAsync = false,
IsVoid = true, IsVoid = true,
ReturnType = null, ReturnType = null,
Invoking = ((instance, parameters, special) => Invoking = (instance, _, _) =>
{ {
(instance as IDisposable)?.Dispose(); (instance as IDisposable)?.Dispose();
return null; return null;
}) },
SuitableType = typeof(IDisposable)
}; };
} }
} }
+4 -4
View File
@@ -22,11 +22,11 @@ namespace mROA.Implementation
public int Id => _identifier.ContextId; public int Id => _identifier.ContextId;
public int OwnerId => _identifier.OwnerId; public int OwnerId => _identifier.OwnerId;
public UniversalObjectIdentifier Identifier => _identifier; public UniversalObjectIdentifier Identifier => _identifier;
protected async Task<T> GetResultAsync<T>(int methodId, object? parameter = default, protected async Task<T> GetResultAsync<T>(int methodId, object?[]? parameters = null,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
var request = new DefaultCallRequest var request = new DefaultCallRequest
{ CommandId = methodId, ObjectId = _identifier.ContextId, Parameter = parameter { CommandId = methodId, ObjectId = _identifier.ContextId, Parameters = parameters
}; };
await _representationModule.PostCallMessageAsync(request.Id, MessageType.CallRequest, request); await _representationModule.PostCallMessageAsync(request.Id, MessageType.CallRequest, request);
@@ -76,11 +76,11 @@ namespace mROA.Implementation
throw errorResponse.Result.GetException(); throw errorResponse.Result.GetException();
} }
protected async Task CallAsync(int methodId, object? parameter = default, protected async Task CallAsync(int methodId, object?[]? parameters = null,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
var request = new DefaultCallRequest var request = new DefaultCallRequest
{ CommandId = methodId, ObjectId = _identifier.ContextId, Parameter = parameter { CommandId = methodId, ObjectId = _identifier.ContextId, Parameters = parameters
}; };
await _representationModule.PostCallMessageAsync(request.Id, MessageType.CallRequest, request); await _representationModule.PostCallMessageAsync(request.Id, MessageType.CallRequest, request);
+16
View File
@@ -0,0 +1,16 @@
using System;
namespace mROA.Implementation
{
public sealed class RequestContext
{
public int OwnerId { get; }
public Guid RequestId { get; }
public RequestContext(Guid requestId, int ownerId)
{
RequestId = requestId;
OwnerId = ownerId;
}
}
}