База для нового бэкэнда
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Net;
|
||||
using Example.Backend;
|
||||
using Example.Shared;
|
||||
using mROA.Abstract;
|
||||
using mROA.Cbor;
|
||||
using mROA.Codegen;
|
||||
@@ -48,5 +49,6 @@ class Program
|
||||
var gateway = builder.GetModule<IGatewayModule>();
|
||||
|
||||
gateway.Run();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ namespace Example.Frontend
|
||||
public string GetName()
|
||||
{
|
||||
Console.WriteLine("ClientBasedPrinter called from server!!!!!!!!!!! Vova likes that:)");
|
||||
|
||||
return "ClientBasedPrinter from mroa";
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class Program
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var builder = new FullMixBuilder();
|
||||
new RemoteTypeBinder();
|
||||
// new RemoteTypeBinder();
|
||||
// builder.Modules.Add(new JsonSerializationToolkit());
|
||||
builder.Modules.Add(new CborSerializationToolkit());
|
||||
|
||||
@@ -106,5 +106,7 @@ class Program
|
||||
// Console.WriteLine("X is {0}", x);
|
||||
// Console.WriteLine("Time : {0}", timer.Elapsed.TotalMilliseconds);
|
||||
// Console.WriteLine($"Time per call: {timer.Elapsed.TotalMilliseconds / iterations} ms");
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using mROA.Implementation;
|
||||
using mROA.Implementation.Attributes;
|
||||
|
||||
namespace Example.Shared
|
||||
{
|
||||
// [SharedObjectInterface]
|
||||
// public interface IDataList<T> : IShared
|
||||
// {
|
||||
// T Get(int index);
|
||||
// void Add(T item);
|
||||
// void Set(int index, T item);
|
||||
// }
|
||||
public interface IDataList<T> : IShared, IDisposable
|
||||
{
|
||||
IReadOnlyList<T> Collection { get; }
|
||||
T Get(int index);
|
||||
void Add(T item);
|
||||
void Set(int index, T item);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using mROA.Implementation.Attributes;
|
||||
|
||||
namespace Example.Shared
|
||||
{
|
||||
[SharedObjectInterface]
|
||||
public interface IPagesList : IDataList<IPage>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -52,8 +52,11 @@ namespace mROA.Cbor
|
||||
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)
|
||||
return nonCasted;
|
||||
|
||||
|
||||
@@ -17,74 +17,57 @@ namespace mROA.Codegen
|
||||
[Generator]
|
||||
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,
|
||||
ImmutableArray<InterfaceDeclarationSyntax> classes)
|
||||
{
|
||||
var methods = new List<(string, IMethodSymbol)>();
|
||||
var frontendContextRepo = new List<string>();
|
||||
// Go through all filtered class declarations.
|
||||
|
||||
var declarations = classes.ToList().OrderBy(i => i.Identifier.Text).ToList();
|
||||
foreach (var classDeclarationSyntax in declarations)
|
||||
{
|
||||
// We need to get semantic model of the class to retrieve metadata.
|
||||
{
|
||||
var semanticModel = compilation.GetSemanticModel(classDeclarationSyntax.SyntaxTree);
|
||||
|
||||
|
||||
// Symbols allow us to get the compile-time information.
|
||||
if (semanticModel.GetDeclaredSymbol(classDeclarationSyntax) is not INamedTypeSymbol classSymbol)
|
||||
continue;
|
||||
|
||||
|
||||
|
||||
var namespaceName = classSymbol.ContainingNamespace.ToDisplayString();
|
||||
|
||||
|
||||
|
||||
// 'Identifier' means the token of the node. Get class name from the syntax node.
|
||||
var className = classDeclarationSyntax.Identifier.Text;
|
||||
|
||||
// Go through all class members with a particular type (property) to generate method lines.
|
||||
var methodBody = classSymbol.GetMembers()
|
||||
.OfType<IMethodSymbol>().OrderBy(i => i.Name);
|
||||
|
||||
var methodBody = CollectMethods(classSymbol);
|
||||
|
||||
var originalName = className;
|
||||
// Build up the source code
|
||||
|
||||
className = className.TrimStart('I') + "RemoteEndpoint";
|
||||
|
||||
|
||||
var methodsText = new List<string>();
|
||||
|
||||
|
||||
foreach (var method in methodBody)
|
||||
{
|
||||
var index = methods.Count;
|
||||
methods.Add((namespaceName + "." + originalName, method));
|
||||
var sb = new StringBuilder();
|
||||
|
||||
bool isParametrized;
|
||||
|
||||
bool isAsync = method.ReturnType.Name == "Task";
|
||||
bool isVoid = method.ReturnType.Name == "Void" ||
|
||||
method.ReturnType.ToString() == "System.Threading.Tasks.Task";
|
||||
bool isParametrized = method.Parameters.Length == 1 && !isAsync ||
|
||||
method.Parameters.Length == 2 && isAsync;
|
||||
bool isAsync;
|
||||
bool isVoid;
|
||||
|
||||
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
|
||||
sb.AppendLine("public" + (isAsync
|
||||
@@ -140,7 +123,7 @@ namespace {namespaceName}
|
||||
|
||||
|
||||
// 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(
|
||||
$"{{ typeof({classSymbol.ToDisplayString()}), typeof({namespaceName}.{className}) }}");
|
||||
@@ -148,31 +131,27 @@ namespace {namespaceName}
|
||||
|
||||
if (methods.Count != 0)
|
||||
{
|
||||
// var methodsStringed = methods.Select(i =>
|
||||
// $"typeof({i.Item1}).GetMethod(\"{i.Item2.Name}\", new Type[] {{{string.Join(", ", i.Item2.Parameters.Select(p => $"typeof({p.Type.ToDisplayString()})"))}}})")
|
||||
// .ToList();
|
||||
var methodsStringed = methods.Select(i =>
|
||||
$"typeof({i.Item1}).GetMethod(\"{i.Item2.Name}\")")
|
||||
.ToList();
|
||||
var methodsStringed = Array.Empty<string>();
|
||||
|
||||
var coCodegenRepoCode = @$"// <auto-generated/>
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using mROA.Abstract;
|
||||
using mROA.Implementation;
|
||||
using System;
|
||||
|
||||
namespace mROA.Codegen
|
||||
{{
|
||||
public class CoCodegenMethodRepository : IMethodRepository
|
||||
{{
|
||||
private readonly List<MethodInfo> _methods = new () {{
|
||||
private readonly List<IMethodInvoker> _methods = new () {{
|
||||
{string.Join(",\r\n\t\t\t", methodsStringed)}
|
||||
}};
|
||||
|
||||
public MethodInfo GetMethod(int id)
|
||||
public IMethodInvoker GetMethod(int id)
|
||||
{{
|
||||
if (id == -1)
|
||||
return typeof(IDisposable).GetMethod(""Dispose"");
|
||||
return mROA.Implementation.MethodInvoker.Dispose;
|
||||
|
||||
if (_methods.Count <= id)
|
||||
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)
|
||||
@@ -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)
|
||||
{
|
||||
var type = taskType.ToString();
|
||||
type = type.Substring(type.IndexOf('<') + 1);
|
||||
return type.Substring(0, type.Length - 1);
|
||||
return (taskType as INamedTypeSymbol).TypeParameters[0].ToDisplayString();
|
||||
}
|
||||
|
||||
public void Initialize(GeneratorInitializationContext context)
|
||||
@@ -266,8 +243,7 @@ namespace mROA.Codegen
|
||||
private bool ContainsSOIAttribute(SyntaxList<AttributeListSyntax> attributes, GeneratorExecutionContext context,
|
||||
InterfaceDeclarationSyntax interfaceDeclarationSyntax)
|
||||
{
|
||||
foreach (AttributeListSyntax attributeListSyntax in attributes)
|
||||
foreach (AttributeSyntax attributeSyntax in attributeListSyntax.Attributes)
|
||||
foreach (var attributeSyntax in attributes.SelectMany(attributeListSyntax => attributeListSyntax.Attributes))
|
||||
{
|
||||
if (context.Compilation.GetSemanticModel(interfaceDeclarationSyntax.SyntaxTree)
|
||||
.GetSymbolInfo(attributeSyntax).Symbol is not IMethodSymbol attributeSymbol)
|
||||
@@ -282,5 +258,16 @@ namespace mROA.Codegen
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ namespace mROA.Abstract
|
||||
bool IsVoid { get; }
|
||||
Type[] ParameterTypes { get; }
|
||||
Type? ReturnType { get; }
|
||||
object? Invoke(object instance, object?[] parameters, object[] special);
|
||||
object? Invoke(object instance, object?[]? parameters, object[] special);
|
||||
Type SuitableType { get; }
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,6 @@ namespace mROA.Abstract
|
||||
{
|
||||
public interface IMethodRepository : IInjectableModule
|
||||
{
|
||||
MethodInfo GetMethod(int id);
|
||||
IMethodInvoker GetMethod(int id);
|
||||
}
|
||||
}
|
||||
@@ -10,8 +10,8 @@ namespace mROA.Abstract
|
||||
object? Deserialize(byte[] rawData, Type type);
|
||||
T? Deserialize<T>(Span<byte> rawData);
|
||||
object? Deserialize(Span<byte> rawData, Type type);
|
||||
T? Cast<T>(object nonCasted);
|
||||
object? Cast(object nonCasted, Type type);
|
||||
T? Cast<T>(object? nonCasted);
|
||||
object? Cast(object? nonCasted, Type type);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -11,11 +12,22 @@ namespace mROA.Implementation.Backend
|
||||
{
|
||||
private IMethodRepository? _methodRepo;
|
||||
private ICancellationRepository? _cancellationRepo;
|
||||
private ISerializationToolkit? _serialization;
|
||||
|
||||
public void Inject<T>(T dependency)
|
||||
{
|
||||
if (dependency is IMethodRepository methodRepo) _methodRepo = methodRepo;
|
||||
if (dependency is ICancellationRepository cancellationRepo) _cancellationRepo = cancellationRepo;
|
||||
switch (dependency)
|
||||
{
|
||||
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,
|
||||
@@ -24,50 +36,69 @@ namespace mROA.Implementation.Backend
|
||||
#if TRACE
|
||||
Console.WriteLine(command.GetType().Name);
|
||||
#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
|
||||
{
|
||||
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 TRACE
|
||||
@@ -80,23 +111,22 @@ namespace mROA.Implementation.Backend
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
throw;
|
||||
return new ExceptionCommandExecution
|
||||
{
|
||||
Id = command.Id,
|
||||
Exception = e.ToString()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private static ICommandExecution Execute(MethodInfo currentCommand, object context, object? parameter,
|
||||
ICallRequest command)
|
||||
private static ICommandExecution Execute(IMethodInvoker invoker, object instance, object?[] parameter,
|
||||
ICallRequest command, RequestContext executionContext)
|
||||
{
|
||||
try
|
||||
{
|
||||
var finalParameter = parameter is null
|
||||
? Array.Empty<object>()
|
||||
: new[]
|
||||
{ parameter };
|
||||
var finalResult = currentCommand.Invoke(context, finalParameter);
|
||||
var finalResult = invoker.Invoke(instance, parameter, new object[] { executionContext });
|
||||
|
||||
if (currentCommand.ReturnType.Name == "Void")
|
||||
if (invoker.IsVoid)
|
||||
{
|
||||
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,
|
||||
IRepresentationModule representationModule)
|
||||
IRepresentationModule representationModule, RequestContext executionContext)
|
||||
{
|
||||
var tokenSource = new CancellationTokenSource();
|
||||
cancellationRepository.RegisterCancellation(command.Id, tokenSource);
|
||||
@@ -132,11 +162,7 @@ namespace mROA.Implementation.Backend
|
||||
#endif
|
||||
try
|
||||
{
|
||||
var finalParameter = parameter is null
|
||||
? new object[] { token }
|
||||
: new[]
|
||||
{ parameter, token };
|
||||
var result = (Task)currentCommand.Invoke(context, finalParameter)!;
|
||||
var result = (Task)invoker.Invoke(instance, parameters, new object[] { executionContext, token })!;
|
||||
|
||||
|
||||
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,
|
||||
IRepresentationModule representationModule)
|
||||
IRepresentationModule representationModule, RequestContext executionContext)
|
||||
{
|
||||
var tokenSource = new CancellationTokenSource();
|
||||
cancellationRepository.RegisterCancellation(command.Id, tokenSource);
|
||||
@@ -183,12 +209,8 @@ namespace mROA.Implementation.Backend
|
||||
var token = tokenSource.Token;
|
||||
try
|
||||
{
|
||||
var finalParameter = parameter is null
|
||||
? new object[] { token }
|
||||
: new[]
|
||||
{ parameter, token };
|
||||
var result =
|
||||
(Task)currentCommand.Invoke(context, finalParameter)!;
|
||||
(Task)invoker.Invoke(instance, parameters, new object[] { executionContext, token })!;
|
||||
|
||||
result.ContinueWith(t =>
|
||||
{
|
||||
@@ -198,7 +220,7 @@ namespace mROA.Implementation.Backend
|
||||
Id = command.Id,
|
||||
Result = finalResult
|
||||
};
|
||||
_cancellationRepo.FreeCancelation(command.Id);
|
||||
_cancellationRepo!.FreeCancelation(command.Id);
|
||||
|
||||
var multiClientOwnershipRepository =
|
||||
TransmissionConfig.OwnershipRepository as MultiClientOwnershipRepository;
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace mROA.Implementation
|
||||
Guid Id { get; }
|
||||
int CommandId { get; }
|
||||
int ObjectId { get; }
|
||||
object? Parameter { get; }
|
||||
object?[]? Parameters { get; }
|
||||
}
|
||||
|
||||
public class DefaultCallRequest : ICallRequest
|
||||
@@ -20,7 +20,7 @@ namespace mROA.Implementation
|
||||
public int CommandId { get; set; }
|
||||
public int ObjectId { get; set; } = -1;
|
||||
|
||||
public object? Parameter { get; set; }
|
||||
public object?[]? Parameters { get; set; }
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Call request {{ Id : {Id}, CommandId : {CommandId}, ObjectId : {ObjectId} }}";
|
||||
@@ -32,7 +32,7 @@ namespace mROA.Implementation
|
||||
public Guid Id { get; set; }
|
||||
public int CommandId { 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()
|
||||
{
|
||||
return $"Cancel request {{ Id : {Id}, CommandId : {CommandId}, ObjectId : {ObjectId} }}";
|
||||
|
||||
@@ -94,15 +94,6 @@ namespace mROA.Implementation.Frontend
|
||||
tokenSource.Cancel();
|
||||
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 resultType = MessageType.Unknown;
|
||||
|
||||
@@ -9,23 +9,26 @@ namespace mROA.Implementation
|
||||
public bool IsVoid { get; set; }
|
||||
public Type[] ParameterTypes { get; set; } = Type.EmptyTypes;
|
||||
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);
|
||||
}
|
||||
|
||||
public static MethodInvoker Dispose = new MethodInvoker
|
||||
public Type SuitableType { get; set; } = null!;
|
||||
|
||||
public static readonly IMethodInvoker Dispose = new MethodInvoker
|
||||
{
|
||||
IsAsync = false,
|
||||
IsVoid = true,
|
||||
ReturnType = null,
|
||||
Invoking = ((instance, parameters, special) =>
|
||||
Invoking = (instance, _, _) =>
|
||||
{
|
||||
(instance as IDisposable)?.Dispose();
|
||||
return null;
|
||||
})
|
||||
},
|
||||
SuitableType = typeof(IDisposable)
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -22,11 +22,11 @@ namespace mROA.Implementation
|
||||
public int Id => _identifier.ContextId;
|
||||
public int OwnerId => _identifier.OwnerId;
|
||||
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)
|
||||
{
|
||||
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);
|
||||
@@ -76,11 +76,11 @@ namespace mROA.Implementation
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user