тесты на работу модуля исполнения работают

This commit is contained in:
2025-01-12 14:17:19 +03:00
parent c9cd6ec0c0
commit 1a55131cb3
11 changed files with 158 additions and 47 deletions
+37
View File
@@ -0,0 +1,37 @@
using mROA.Implementation;
namespace mROA.Test;
[SharedObjectInterafce]
public interface ITestController
{
void A();
Task AAsync(CancellationToken cancellationToken);
int B();
Task<int> BAsync(CancellationToken cancellationToken);
}
[SharedObjectSingleton]
public class TestController : ITestController
{
private int _bOut = 5;
public void A()
{
Console.WriteLine("A called");
}
public Task AAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
public int B()
{
return _bOut++;
}
public Task<int> BAsync(CancellationToken cancellationToken)
{
return Task.FromResult(5);
}
}
+1
View File
@@ -5,4 +5,5 @@ public interface IContextRepository
int ResisterObject(object o);
void ClearObject(int id);
object GetObject(int id);
object GetSingleObject(Type type);
}
@@ -2,8 +2,9 @@ using mROA.Implementation;
namespace mROA;
public interface IInputModule
public interface ISerialisationModule
{
void HandleIncomingRequest(int clientId, string command);
void PostResponse(ICommandExecution call);
void SetExecuteModule(IExecuteModule executeModule);
}
+4 -4
View File
@@ -7,14 +7,14 @@ public interface ICallRequest
int ClientId { get; set; }
}
public class StaticCallRequest : ICallRequest
public class SingletonCallRequest : ICallRequest
{
public virtual int RequestTypeId => (int)RequestType.Static;
public virtual int RequestTypeId => (int)RequestType.Singleton;
public int CommandId { get; set; }
public int ClientId { get; set; }
}
public class CallRequest : StaticCallRequest
public class CallRequest : SingletonCallRequest
{
public override int RequestTypeId => (int)RequestType.NonParametrized;
public int ObjectId { get; set; }
@@ -28,7 +28,7 @@ public class ParametrizedCallRequest : CallRequest
enum RequestType
{
Static,
Singleton,
NonParametrized,
Parametrized
}
+18 -2
View File
@@ -1,7 +1,11 @@
namespace mROA.Implementation;
using System.Collections.Frozen;
using System.Reflection;
namespace mROA.Implementation;
public class ContextRepository : IContextRepository
{
private FrozenDictionary<int, object?> _singletons;
private object[] _storage;
private int _lastIndex;
@@ -16,6 +20,14 @@ public class ContextRepository : IContextRepository
_storage = new object[StartupSize];
}
public void FillSingletons(Assembly assembly)
{
var types = assembly.GetTypes().Where(type =>
type is { IsClass: true, IsAbstract: false, IsGenericType: false } &&
type.GetCustomAttributes(typeof(SharedObjectSingletonAttribute), true).Length > 0);
_singletons = types.ToFrozenDictionary(t => t.GetInterfaces().FirstOrDefault(i => i.GetCustomAttributes(typeof(SharedObjectInterafceAttribute), true).Length > 0)!.GetHashCode(), Activator.CreateInstance);
}
public int ResisterObject(object o)
{
if (_lastIndexFinder is not null)
@@ -42,6 +54,11 @@ public class ContextRepository : IContextRepository
return _storage.Length == -1 || _storage.Length <= id ? null : _storage[id];
}
public object GetSingleObject(Type type)
{
return _singletons.TryGetValue(type.GetHashCode(), out var value) ? value : null;
}
private async Task<int> FindLastIndex()
{
for (int i = 0; i < _storage.Length; i++)
@@ -54,5 +71,4 @@ public class ContextRepository : IContextRepository
Array.Copy(_storage, nextStorage, _storage.Length);
return _storage.Length;
}
}
@@ -4,18 +4,18 @@ using System.Text.Json.Serialization;
namespace mROA.Implementation;
public class InputModule : IInputModule
public class JsonSerialisationModule : ISerialisationModule
{
private readonly IInteractionModule _dataSource;
private readonly IExecuteModule _executeModule;
public InputModule(IInteractionModule dataSource, IExecuteModule executeModule)
private IExecuteModule _executeModule;
public JsonSerialisationModule(IInteractionModule dataSource)
{
_dataSource = dataSource;
_executeModule = executeModule;
_dataSource.SetMessageHandler(HandleIncomingRequest);
}
public void SetExecuteModule(IExecuteModule executeModule) => _executeModule = executeModule;
public void HandleIncomingRequest(int clientId, string command)
{
var type = JsonDocument.Parse(command).RootElement.GetProperty("RequestTypeId").GetInt32();
@@ -25,7 +25,7 @@ public class InputModule : IInputModule
switch (type)
{
case 0:
request = JsonSerializer.Deserialize<StaticCallRequest>(command);
request = JsonSerializer.Deserialize<SingletonCallRequest>(command);
break;
case 1:
request = JsonSerializer.Deserialize<CallRequest>(command);
@@ -34,27 +34,25 @@ public class InputModule : IInputModule
request = JsonSerializer.Deserialize<ParametrizedCallRequest>(command);
break;
default:
request = JsonSerializer.Deserialize<StaticCallRequest>(command);
request = JsonSerializer.Deserialize<SingletonCallRequest>(command);
break;
}
request.ClientId = clientId;
var response = _executeModule.Execute(request);
var texted = string.Empty;
if (response is FinalCommandExecution finalCommand)
{
texted = JsonSerializer.Serialize(finalCommand);
}else if (response is AsyncCommandExecution asyncCommand)
{
texted = JsonSerializer.Serialize(asyncCommand);
}
var binary = Encoding.UTF8.GetBytes(texted);
_dataSource.SendTo(clientId, binary);
PostResponse(response);
}
public void PostResponse(ICommandExecution call)
{
var texted = JsonSerializer.Serialize(call);
var texted = string.Empty;
if (call is FinalCommandExecution finalCommand)
{
texted = JsonSerializer.Serialize(finalCommand);
}else if (call is AsyncCommandExecution asyncCommand)
{
texted = JsonSerializer.Serialize(asyncCommand);
}
var binary = Encoding.UTF8.GetBytes(texted);
_dataSource.SendTo(call.ClientId, binary);
}
+12 -2
View File
@@ -4,11 +4,11 @@ namespace mROA.Implementation;
public class MethodRepository : IMethodRepository
{
private List<MethodInfo> _methods;
private List<MethodInfo> _methods = [];
public MethodInfo GetMethod(int id)
{
if (_methods.Count >= id)
if (_methods.Count <= id)
return null;
return _methods[id];
@@ -24,4 +24,14 @@ public class MethodRepository : IMethodRepository
{
return _methods;
}
public void CollectForAssembly(Assembly assembly)
{
var types = assembly.GetTypes().Where(i => i.IsInterface && i.GetCustomAttributes(typeof(SharedObjectInterafceAttribute), true).Length > 0);
foreach (var type in types)
{
foreach (var method in type.GetMethods())
RegisterMethod(method);
}
}
}
+36 -13
View File
@@ -2,44 +2,67 @@
namespace mROA.Implementation;
public class PrepairedExecutionModule(
IMethodRepository methodRepo,
IInputModule inputModule,
IContextRepository contextRepo)
: IExecuteModule
public class PrepairedExecutionModule : IExecuteModule
{
private readonly IMethodRepository _methodRepo;
private readonly ISerialisationModule _serialisationModule;
private readonly IContextRepository _contextRepo;
private readonly MethodInfo _resultExtractionMethod;
public PrepairedExecutionModule(IMethodRepository methodRepo,
ISerialisationModule serialisationModule,
IContextRepository contextRepo)
{
_methodRepo = methodRepo;
_serialisationModule = serialisationModule;
_contextRepo = contextRepo;
_serialisationModule.SetExecuteModule(this);
}
public ICommandExecution Execute(ICallRequest command)
{
var currentCommand = methodRepo.GetMethod(command.CommandId);
var currentCommand = _methodRepo.GetMethod(command.CommandId);
if (currentCommand == null)
throw new Exception($"Command {command.CommandId} not found");
var context = command is CallRequest request ? contextRepo.GetObject(request.ObjectId) : null;
var context = command is CallRequest request ? _contextRepo.GetObject(request.ObjectId) : _contextRepo.GetSingleObject(currentCommand.DeclaringType);
var parameter = command is ParametrizedCallRequest callRequest ? callRequest.Parameter : null;
if (currentCommand.ReturnType == typeof(Task<>))
if (currentCommand.ReturnType.BaseType == typeof(Task) && currentCommand.ReturnType.GenericTypeArguments.Length == 1)
{
var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
var result =
currentCommand.Invoke(context, parameter is null ? [token] : [parameter, token]) as Task<object>;
currentCommand.Invoke(context, parameter is null ? [token] : [parameter, token]) as Task;
var exec = new AsyncCommandExecution(tokenSource)
{ CommandId = command.CommandId, ClientId = command.ClientId };
result.ContinueWith(task =>
{
var result = task.Result;
inputModule.PostResponse(new FinalCommandExecution
var result = task.GetType().GetProperty("Result").GetValue(task);
_serialisationModule.PostResponse(new FinalCommandExecution
{
ExecutionId = exec.ExecutionId, Result = result, CommandId = command.CommandId,
ClientId = command.ClientId
});
}, token);
// result.ContinueWith(task =>
// {
// var result = task.Result;
// _serialisationModule.PostResponse(new FinalCommandExecution
// {
// ExecutionId = exec.ExecutionId, Result = result, CommandId = command.CommandId,
// ClientId = command.ClientId
// });
// }, token);
return exec;
}
else
if (currentCommand.ReturnType == typeof(Task))
{
var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
@@ -50,7 +73,7 @@ public class PrepairedExecutionModule(
result.ContinueWith(_ =>
{
inputModule.PostResponse(new FinalCommandExecution
_serialisationModule.PostResponse(new FinalCommandExecution
{
ExecutionId = exec.ExecutionId, Result = null, CommandId = command.CommandId,
ClientId = command.ClientId
@@ -0,0 +1,3 @@
namespace mROA.Implementation;
public class SharedObjectInterafceAttribute : Attribute;
@@ -0,0 +1,3 @@
namespace mROA.Implementation;
public class SharedObjectSingletonAttribute : Attribute;
@@ -0,0 +1,19 @@
namespace mROA.Implementation;
public class MockSerializationModule : ISerialisationModule
{
public void HandleIncomingRequest(int clientId, string command)
{
}
public void PostResponse(ICommandExecution call)
{
}
public void SetExecuteModule(IExecuteModule executeModule)
{
}
}