From c802f337c7528e151862504ccf20325ea2ac323b Mon Sep 17 00:00:00 2001 From: Mikhail Mitrofanov Date: Thu, 6 Mar 2025 14:10:52 +0300 Subject: [PATCH] =?UTF-8?q?=D0=91=D0=B0=D0=B7=D0=B0=20=D0=B4=D0=BB=D1=8F?= =?UTF-8?q?=20=D0=BD=D0=BE=D0=B2=D0=BE=D0=B3=D0=BE=20=D0=B1=D1=8D=D0=BA?= =?UTF-8?q?=D1=8D=D0=BD=D0=B4=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Example.Backend/CsTest.cs | 18 ++ Example.Backend/PagesList.cs | 24 +++ Example.Backend/Program.cs | 2 + Example.Frontend/ClientBasedPrinter.cs | 1 + Example.Frontend/Program.cs | 4 +- Example.Shared/IDataList.cs | 17 +- Example.Shared/IPagesList.cs | 9 + mROA.Cbor/CborSerializationToolkit.cs | 5 +- mROA.Codegen/mROASourceGenerator.cs | 109 ++++++------ mROA/Abstract/IMethodInvoker.cs | 3 +- mROA/Abstract/IMethodRepository.cs | 2 +- mROA/Abstract/ISerializationToolkit.cs | 4 +- .../Backend/BasicExecutionModule.cs | 158 ++++++++++-------- mROA/Implementation/CallRequest.cs | 6 +- .../Frontend/RequestExtractor.cs | 9 - mROA/Implementation/MethodInvoker.cs | 13 +- mROA/Implementation/RemoteObjectBase.cs | 8 +- mROA/Implementation/RequestContext.cs | 16 ++ 18 files changed, 245 insertions(+), 163 deletions(-) create mode 100644 Example.Backend/CsTest.cs create mode 100644 Example.Backend/PagesList.cs create mode 100644 Example.Shared/IPagesList.cs create mode 100644 mROA/Implementation/RequestContext.cs diff --git a/Example.Backend/CsTest.cs b/Example.Backend/CsTest.cs new file mode 100644 index 0000000..8db1c75 --- /dev/null +++ b/Example.Backend/CsTest.cs @@ -0,0 +1,18 @@ +using System; +using Example.Shared; + +namespace Example.Backend +{ + public class CsTest + { + public T FinalCasted(IDataList list, int index) + { + return list.Get(index); + } + + public object NonCasted(object list, int index) + { + return FinalCasted(list as IDataList, index); + } + } +} \ No newline at end of file diff --git a/Example.Backend/PagesList.cs b/Example.Backend/PagesList.cs new file mode 100644 index 0000000..6505303 --- /dev/null +++ b/Example.Backend/PagesList.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; +using Example.Shared; + +namespace Example.Backend +{ + public class PagesList : IPagesList + { + public IReadOnlyList 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(); + } + } +} \ No newline at end of file diff --git a/Example.Backend/Program.cs b/Example.Backend/Program.cs index f31f557..a6b3ffc 100644 --- a/Example.Backend/Program.cs +++ b/Example.Backend/Program.cs @@ -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(); gateway.Run(); + } } \ No newline at end of file diff --git a/Example.Frontend/ClientBasedPrinter.cs b/Example.Frontend/ClientBasedPrinter.cs index b449a6d..4d9c661 100644 --- a/Example.Frontend/ClientBasedPrinter.cs +++ b/Example.Frontend/ClientBasedPrinter.cs @@ -11,6 +11,7 @@ namespace Example.Frontend public string GetName() { Console.WriteLine("ClientBasedPrinter called from server!!!!!!!!!!! Vova likes that:)"); + return "ClientBasedPrinter from mroa"; } diff --git a/Example.Frontend/Program.cs b/Example.Frontend/Program.cs index 6eb9181..d47c620 100644 --- a/Example.Frontend/Program.cs +++ b/Example.Frontend/Program.cs @@ -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"); + + } } \ No newline at end of file diff --git a/Example.Shared/IDataList.cs b/Example.Shared/IDataList.cs index 44eea30..c0e2cc7 100644 --- a/Example.Shared/IDataList.cs +++ b/Example.Shared/IDataList.cs @@ -1,12 +1,15 @@ +using System; +using System.Collections.Generic; +using mROA.Implementation; using mROA.Implementation.Attributes; namespace Example.Shared { - // [SharedObjectInterface] - // public interface IDataList : IShared - // { - // T Get(int index); - // void Add(T item); - // void Set(int index, T item); - // } + public interface IDataList : IShared, IDisposable + { + IReadOnlyList Collection { get; } + T Get(int index); + void Add(T item); + void Set(int index, T item); + } } \ No newline at end of file diff --git a/Example.Shared/IPagesList.cs b/Example.Shared/IPagesList.cs new file mode 100644 index 0000000..05bcc6a --- /dev/null +++ b/Example.Shared/IPagesList.cs @@ -0,0 +1,9 @@ +using mROA.Implementation.Attributes; + +namespace Example.Shared +{ + [SharedObjectInterface] + public interface IPagesList : IDataList + { + } +} \ No newline at end of file diff --git a/mROA.Cbor/CborSerializationToolkit.cs b/mROA.Cbor/CborSerializationToolkit.cs index 6050272..847f2cc 100644 --- a/mROA.Cbor/CborSerializationToolkit.cs +++ b/mROA.Cbor/CborSerializationToolkit.cs @@ -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; diff --git a/mROA.Codegen/mROASourceGenerator.cs b/mROA.Codegen/mROASourceGenerator.cs index 28438f3..7881618 100644 --- a/mROA.Codegen/mROASourceGenerator.cs +++ b/mROA.Codegen/mROASourceGenerator.cs @@ -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 = $@"// - -namespace {Namespace} -{{ - [System.AttributeUsage(System.AttributeTargets.Class)] - public class {AttributeName} : System.Attribute - {{ - }} -}}"; - - /// - /// Generate code action. - /// It will be executed on specific nodes (ClassDeclarationSyntax annotated with the [Report] attribute) changed by the user. - /// - /// Source generation context used to add source files. - /// Compilation used to provide access to the Semantic Model. - /// Nodes annotated with the [Report] attribute that trigger the generate action. private void GenerateCode(GeneratorExecutionContext context, Compilation compilation, ImmutableArray classes) { var methods = new List<(string, IMethodSymbol)>(); var frontendContextRepo = new List(); - // 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().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(); - + 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(); var coCodegenRepoCode = @$"// 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 _methods = new () {{ + private readonly List _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 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 CollectMethods(INamedTypeSymbol type) + { + var methods = type.GetMembers().OfType().ToList(); + foreach (var inner in type.AllInterfaces) + { + methods.AddRange(inner.GetMembers().OfType()); + } + + return methods.OrderBy(i => i.Name).ToList(); + } } } \ No newline at end of file diff --git a/mROA/Abstract/IMethodInvoker.cs b/mROA/Abstract/IMethodInvoker.cs index 35ec3b1..439434a 100644 --- a/mROA/Abstract/IMethodInvoker.cs +++ b/mROA/Abstract/IMethodInvoker.cs @@ -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; } } } \ No newline at end of file diff --git a/mROA/Abstract/IMethodRepository.cs b/mROA/Abstract/IMethodRepository.cs index a08faf8..ec67928 100644 --- a/mROA/Abstract/IMethodRepository.cs +++ b/mROA/Abstract/IMethodRepository.cs @@ -4,6 +4,6 @@ namespace mROA.Abstract { public interface IMethodRepository : IInjectableModule { - MethodInfo GetMethod(int id); + IMethodInvoker GetMethod(int id); } } \ No newline at end of file diff --git a/mROA/Abstract/ISerializationToolkit.cs b/mROA/Abstract/ISerializationToolkit.cs index b3502f8..c7ce9f4 100644 --- a/mROA/Abstract/ISerializationToolkit.cs +++ b/mROA/Abstract/ISerializationToolkit.cs @@ -10,8 +10,8 @@ namespace mROA.Abstract object? Deserialize(byte[] rawData, Type type); T? Deserialize(Span rawData); object? Deserialize(Span rawData, Type type); - T? Cast(object nonCasted); - object? Cast(object nonCasted, Type type); + T? Cast(object? nonCasted); + object? Cast(object? nonCasted, Type type); } } \ No newline at end of file diff --git a/mROA/Implementation/Backend/BasicExecutionModule.cs b/mROA/Implementation/Backend/BasicExecutionModule.cs index 443a366..31e9ee1 100644 --- a/mROA/Implementation/Backend/BasicExecutionModule.cs +++ b/mROA/Implementation/Backend/BasicExecutionModule.cs @@ -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 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(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(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() - : 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; diff --git a/mROA/Implementation/CallRequest.cs b/mROA/Implementation/CallRequest.cs index a6235f1..9066319 100644 --- a/mROA/Implementation/CallRequest.cs +++ b/mROA/Implementation/CallRequest.cs @@ -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} }}"; diff --git a/mROA/Implementation/Frontend/RequestExtractor.cs b/mROA/Implementation/Frontend/RequestExtractor.cs index cfcf9ce..c08f21a 100644 --- a/mROA/Implementation/Frontend/RequestExtractor.cs +++ b/mROA/Implementation/Frontend/RequestExtractor.cs @@ -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; diff --git a/mROA/Implementation/MethodInvoker.cs b/mROA/Implementation/MethodInvoker.cs index 337ec46..8299a0a 100644 --- a/mROA/Implementation/MethodInvoker.cs +++ b/mROA/Implementation/MethodInvoker.cs @@ -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 Invoking { get; set; } + public Func 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) }; } } \ No newline at end of file diff --git a/mROA/Implementation/RemoteObjectBase.cs b/mROA/Implementation/RemoteObjectBase.cs index b74b58a..e756d5a 100644 --- a/mROA/Implementation/RemoteObjectBase.cs +++ b/mROA/Implementation/RemoteObjectBase.cs @@ -22,11 +22,11 @@ namespace mROA.Implementation public int Id => _identifier.ContextId; public int OwnerId => _identifier.OwnerId; public UniversalObjectIdentifier Identifier => _identifier; - protected async Task GetResultAsync(int methodId, object? parameter = default, + protected async Task GetResultAsync(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); diff --git a/mROA/Implementation/RequestContext.cs b/mROA/Implementation/RequestContext.cs new file mode 100644 index 0000000..9daf956 --- /dev/null +++ b/mROA/Implementation/RequestContext.cs @@ -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; + } + } +} \ No newline at end of file