Теоретически должно работать!!!
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
using System.Net;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
using Example.Backend;
|
using Example.Backend;
|
||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
using mROA.Cbor;
|
using mROA.Cbor;
|
||||||
@@ -23,19 +24,20 @@ class Program
|
|||||||
builder.Modules.Add(new HubRequestExtractor(typeof(RequestExtractor)));
|
builder.Modules.Add(new HubRequestExtractor(typeof(RequestExtractor)));
|
||||||
|
|
||||||
builder.UseBasicExecution();
|
builder.UseBasicExecution();
|
||||||
|
builder.Modules.Add(new CreativeRepresentationModuleProducer(
|
||||||
|
new IInjectableModule[] { builder.GetModule<ISerializationToolkit>()! },
|
||||||
|
typeof(RepresentationModule)));
|
||||||
builder.Modules.Add(new RemoteContextRepository());
|
builder.Modules.Add(new RemoteContextRepository());
|
||||||
// builder.UseCollectableContextRepository(typeof(PrinterFactory).Assembly);
|
// builder.UseCollectableContextRepository(typeof(PrinterFactory).Assembly);
|
||||||
builder.Modules.Add(new MultiClientContextRepository(i =>
|
builder.Modules.Add(new MultiClientContextRepository(i =>
|
||||||
{
|
{
|
||||||
var repo = new ContextRepository();
|
var repo = new ContextRepository();
|
||||||
repo.FillSingletons(typeof(PrinterFactory).Assembly);
|
repo.FillSingletons(typeof(PrinterFactory).Assembly);
|
||||||
|
repo.Inject(builder.Modules.OfType<CreativeRepresentationModuleProducer>().First());
|
||||||
return repo;
|
return repo;
|
||||||
}));
|
}));
|
||||||
builder.SetupMethodsRepository(new CoCodegenMethodRepository());
|
builder.SetupMethodsRepository(new CoCodegenMethodRepository());
|
||||||
builder.Modules.Add(new CreativeRepresentationModuleProducer(
|
|
||||||
new IInjectableModule[] { builder.GetModule<ISerializationToolkit>()! },
|
|
||||||
typeof(RepresentationModule)));
|
|
||||||
builder.Modules.Add(new CancellationRepository());
|
builder.Modules.Add(new CancellationRepository());
|
||||||
|
|
||||||
builder.Build();
|
builder.Build();
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ namespace mROA.Codegen
|
|||||||
// var reader = new StreamReader(test);
|
// var reader = new StreamReader(test);
|
||||||
// var allText = reader.ReadToEnd();
|
// var allText = reader.ReadToEnd();
|
||||||
var frontendContextRepo = new List<string>();
|
var frontendContextRepo = new List<string>();
|
||||||
|
var eventBinders = new List<string>();
|
||||||
List<IMethodSymbol> totalMethods = new List<IMethodSymbol>();
|
List<IMethodSymbol> totalMethods = new List<IMethodSymbol>();
|
||||||
|
|
||||||
|
|
||||||
@@ -145,7 +146,7 @@ namespace mROA.Codegen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GenerateEventImplementation(classSymbol, invokers, declaredMethods, context);
|
GenerateEventImplementation(classSymbol, invokers, declaredMethods, context, eventBinders);
|
||||||
|
|
||||||
var code = $@"// <auto-generated/>
|
var code = $@"// <auto-generated/>
|
||||||
|
|
||||||
@@ -222,11 +223,12 @@ namespace mROA.Codegen
|
|||||||
if (frontendContextRepo.Count != 0)
|
if (frontendContextRepo.Count != 0)
|
||||||
{
|
{
|
||||||
var fronendRepoCode = @$"// <auto-generated/>
|
var fronendRepoCode = @$"// <auto-generated/>
|
||||||
using mROA.Implementation;
|
|
||||||
using mROA.Abstract;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System;
|
||||||
|
using mROA.Abstract;
|
||||||
|
using mROA.Implementation.Backend;
|
||||||
|
using mROA.Implementation;
|
||||||
|
|
||||||
namespace mROA.Codegen
|
namespace mROA.Codegen
|
||||||
{{
|
{{
|
||||||
@@ -235,6 +237,8 @@ namespace mROA.Codegen
|
|||||||
static RemoteTypeBinder(){{
|
static RemoteTypeBinder(){{
|
||||||
RemoteContextRepository.RemoteTypes = new Dictionary<Type, Type> {{
|
RemoteContextRepository.RemoteTypes = new Dictionary<Type, Type> {{
|
||||||
{string.Join(", \r\n\t\t\t", frontendContextRepo)}}};
|
{string.Join(", \r\n\t\t\t", frontendContextRepo)}}};
|
||||||
|
ContextRepository.EventBinders = new object[] {{
|
||||||
|
{string.Join(",\r\n\t\t\t", eventBinders)}}};
|
||||||
}}
|
}}
|
||||||
}}
|
}}
|
||||||
}}
|
}}
|
||||||
@@ -246,7 +250,7 @@ namespace mROA.Codegen
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void GenerateEventImplementation(INamedTypeSymbol classSymbol, List<string> invokers,
|
private void GenerateEventImplementation(INamedTypeSymbol classSymbol, List<string> invokers,
|
||||||
List<string> declaredMethods, GeneratorExecutionContext context)
|
List<string> declaredMethods, GeneratorExecutionContext context, List<string> binders)
|
||||||
{
|
{
|
||||||
var events = classSymbol.AllInterfaces.Add(classSymbol).SelectMany(i => i.GetMembers())
|
var events = classSymbol.AllInterfaces.Add(classSymbol).SelectMany(i => i.GetMembers())
|
||||||
.OfType<IEventSymbol>().ToList();
|
.OfType<IEventSymbol>().ToList();
|
||||||
@@ -254,8 +258,7 @@ namespace mROA.Codegen
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
var additionalSignatures = new List<string>(events.Count);
|
var additionalSignatures = new List<string>(events.Count);
|
||||||
var namespaceName = classSymbol.ContainingNamespace.ToDisplayString();
|
var singleEventBinder = new List<string>(events.Count);
|
||||||
|
|
||||||
for (int i = 0; i < events.Count; i++)
|
for (int i = 0; i < events.Count; i++)
|
||||||
{
|
{
|
||||||
var currentEvent = events[i];
|
var currentEvent = events[i];
|
||||||
@@ -264,6 +267,7 @@ namespace mROA.Codegen
|
|||||||
declaredMethods.Add(additionalMethod);
|
declaredMethods.Add(additionalMethod);
|
||||||
additionalSignatures.Add(signature);
|
additionalSignatures.Add(signature);
|
||||||
GenerateEventCode(currentEvent, invokers, classSymbol);
|
GenerateEventCode(currentEvent, invokers, classSymbol);
|
||||||
|
GenerateBinderCode(currentEvent, invokers, classSymbol, singleEventBinder);
|
||||||
}
|
}
|
||||||
|
|
||||||
var partialInterface = $@"
|
var partialInterface = $@"
|
||||||
@@ -275,6 +279,16 @@ namespace {classSymbol.ContainingNamespace.ToDisplayString()}
|
|||||||
}}
|
}}
|
||||||
}}
|
}}
|
||||||
";
|
";
|
||||||
|
var binder = $@"new EventBinder<{classSymbol.ToDisplayString()}>
|
||||||
|
{{
|
||||||
|
BindAction = (instance, context, representationProducer, index) =>
|
||||||
|
{{
|
||||||
|
var module = representationProducer.Produce(context.OwnerId);
|
||||||
|
|
||||||
|
{string.Join("\r\n", singleEventBinder)}
|
||||||
|
}}
|
||||||
|
}}";
|
||||||
|
binders.Add(binder);
|
||||||
#if !DONT_ADD
|
#if !DONT_ADD
|
||||||
context.AddSource($"{classSymbol.Name}.g.cs", SourceText.From(partialInterface, Encoding.UTF8));
|
context.AddSource($"{classSymbol.Name}.g.cs", SourceText.From(partialInterface, Encoding.UTF8));
|
||||||
#endif
|
#endif
|
||||||
@@ -439,6 +453,41 @@ namespace {classSymbol.ContainingNamespace.ToDisplayString()}
|
|||||||
invokers.Add(backend);
|
invokers.Add(backend);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void GenerateBinderCode(IEventSymbol eventSymbol, List<string> invokers, INamedTypeSymbol baseType,
|
||||||
|
List<string> binders)
|
||||||
|
{
|
||||||
|
var index = invokers.Count - 1;
|
||||||
|
var parameters = (eventSymbol.Type as INamedTypeSymbol).TypeArguments.ToList();
|
||||||
|
int parameterIndex = 0;
|
||||||
|
var parametersDeclaration = string.Join(", ",
|
||||||
|
JoinWithComa(Enumerable.Range(0, parameters.Count).Select(i => "p" + i++)));
|
||||||
|
|
||||||
|
var transferParameters =
|
||||||
|
JoinWithComa(parameters.Where(i => ParameterFilterForType(i)).Select(i => "p" + parameters.IndexOf(i)));
|
||||||
|
|
||||||
|
var callFilter = "";
|
||||||
|
|
||||||
|
var requestIndex = parameters.FindIndex(i => i.Name == "RequestContext");
|
||||||
|
if (requestIndex != -1)
|
||||||
|
{
|
||||||
|
callFilter = $"\n\r\t\t\tif(context.OwnerId == p{requestIndex}.OwnerId) return;";
|
||||||
|
}
|
||||||
|
|
||||||
|
var eventBinderCode =
|
||||||
|
$@" (instance as {baseType.ToDisplayString()}).{eventSymbol.Name} += ({parametersDeclaration}) =>
|
||||||
|
{{ {callFilter}
|
||||||
|
var request = new DefaultCallRequest
|
||||||
|
{{
|
||||||
|
CommandId = {index}, ObjectId = index, Parameters = new object[] {{ {transferParameters} }}
|
||||||
|
}};
|
||||||
|
module.PostCallMessageAsync(request.Id, MessageType.EventRequest, request);
|
||||||
|
}};
|
||||||
|
";
|
||||||
|
binders.Add(eventBinderCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string JoinWithComa(IEnumerable<string> parts) => string.Join(", ", parts);
|
||||||
|
|
||||||
private void GenerateEventCode(IEventSymbol eventSymbol, List<string> invokers, ITypeSymbol baseInterface)
|
private void GenerateEventCode(IEventSymbol eventSymbol, List<string> invokers, ITypeSymbol baseInterface)
|
||||||
{
|
{
|
||||||
var level = "\t\t\t";
|
var level = "\t\t\t";
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
{
|
{
|
||||||
public interface IEventBinder<T>
|
public interface IEventBinder<T>
|
||||||
{
|
{
|
||||||
public void BindEvents(T source, IEndPointContext context);
|
public void BindEvents(T source, IEndPointContext context,
|
||||||
|
IRepresentationModuleProducer representationModuleProducer, int index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,38 +10,27 @@ namespace mROA.Implementation.Backend
|
|||||||
{
|
{
|
||||||
public class ContextRepository : IContextRepository
|
public class ContextRepository : IContextRepository
|
||||||
{
|
{
|
||||||
|
private const int StartupSize = 1024;
|
||||||
|
private const int GrowSize = 128;
|
||||||
public static object[] EventBinders = new object[] { };
|
public static object[] EventBinders = new object[] { };
|
||||||
private int _debugId = -1;
|
|
||||||
|
|
||||||
private static int LastDebugId = -1;
|
private static int LastDebugId = -1;
|
||||||
|
private int _debugId = -1;
|
||||||
|
|
||||||
|
private Task<int> _lastIndexFinder = Task.FromResult(0);
|
||||||
|
|
||||||
|
private IRepresentationModuleProducer? _representationModuleProducer;
|
||||||
|
|
||||||
// [CanBeNull]
|
// [CanBeNull]
|
||||||
private Dictionary<int, object?> _singletons;
|
private Dictionary<int, object?> _singletons;
|
||||||
private object?[] _storage;
|
private object?[] _storage;
|
||||||
|
|
||||||
private Task<int> _lastIndexFinder = Task.FromResult(0);
|
|
||||||
|
|
||||||
private const int StartupSize = 1024;
|
|
||||||
private const int GrowSize = 128;
|
|
||||||
|
|
||||||
|
|
||||||
public ContextRepository()
|
public ContextRepository()
|
||||||
{
|
{
|
||||||
_storage = new object[StartupSize];
|
_storage = new object[StartupSize];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FillSingletons(params Assembly[] assembly)
|
|
||||||
{
|
|
||||||
var types = assembly.SelectMany(x => x.GetTypes()).Where(type =>
|
|
||||||
type is { IsClass: true, IsAbstract: false, IsGenericType: false } &&
|
|
||||||
type.GetCustomAttributes(typeof(SharedObjectSingletonAttribute), true).Length > 0);
|
|
||||||
_singletons =
|
|
||||||
types.ToDictionary(
|
|
||||||
t => t.GetInterfaces().FirstOrDefault(i =>
|
|
||||||
i.GetCustomAttributes(typeof(SharedObjectInterfaceAttribute), true).Length > 0)!.GetHashCode(),
|
|
||||||
Activator.CreateInstance);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int ResisterObject<T>(object o, IEndPointContext context)
|
public int ResisterObject<T>(object o, IEndPointContext context)
|
||||||
{
|
{
|
||||||
if (!_lastIndexFinder.IsCompleted)
|
if (!_lastIndexFinder.IsCompleted)
|
||||||
@@ -49,10 +38,11 @@ namespace mROA.Implementation.Backend
|
|||||||
|
|
||||||
_storage[_lastIndexFinder.Result] = o;
|
_storage[_lastIndexFinder.Result] = o;
|
||||||
|
|
||||||
EventBinders.OfType<IEventBinder<T>>().FirstOrDefault()?.BindEvents((T)o, context);
|
|
||||||
|
|
||||||
var last = _lastIndexFinder.Result;
|
var last = _lastIndexFinder.Result;
|
||||||
_lastIndexFinder = Task.Run(FindLastIndex);
|
_lastIndexFinder = Task.Run(FindLastIndex);
|
||||||
|
EventBinders.OfType<IEventBinder<T>>().FirstOrDefault()
|
||||||
|
?.BindEvents((T)o, context, _representationModuleProducer!, last);
|
||||||
|
|
||||||
return last;
|
return last;
|
||||||
}
|
}
|
||||||
@@ -68,12 +58,6 @@ namespace mROA.Implementation.Backend
|
|||||||
return (T)GetObject(sharedObjectShellShell.Identifier.ContextId);
|
return (T)GetObject(sharedObjectShellShell.Identifier.ContextId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object GetObject(int id)
|
|
||||||
{
|
|
||||||
// Debug.Log($"Reading object {id} from repository with debug ID {_debugId}");
|
|
||||||
return (id == -1 || _storage.Length <= id ? null : _storage[id]) ?? throw new NullReferenceException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public T GetObject<T>(int id)
|
public T GetObject<T>(int id)
|
||||||
{
|
{
|
||||||
return id == -1 || _storage.Length <= id
|
return id == -1 || _storage.Length <= id
|
||||||
@@ -93,6 +77,32 @@ namespace mROA.Implementation.Backend
|
|||||||
return index == -1 ? ResisterObject<T>(o, context) : index;
|
return index == -1 ? ResisterObject<T>(o, context) : index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Inject<T>(T dependency)
|
||||||
|
{
|
||||||
|
if (dependency is IRepresentationModuleProducer moduleProducer)
|
||||||
|
{
|
||||||
|
_representationModuleProducer = moduleProducer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FillSingletons(params Assembly[] assembly)
|
||||||
|
{
|
||||||
|
var types = assembly.SelectMany(x => x.GetTypes()).Where(type =>
|
||||||
|
type is { IsClass: true, IsAbstract: false, IsGenericType: false } &&
|
||||||
|
type.GetCustomAttributes(typeof(SharedObjectSingletonAttribute), true).Length > 0);
|
||||||
|
_singletons =
|
||||||
|
types.ToDictionary(
|
||||||
|
t => t.GetInterfaces().FirstOrDefault(i =>
|
||||||
|
i.GetCustomAttributes(typeof(SharedObjectInterfaceAttribute), true).Length > 0)!.GetHashCode(),
|
||||||
|
Activator.CreateInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object GetObject(int id)
|
||||||
|
{
|
||||||
|
// Debug.Log($"Reading object {id} from repository with debug ID {_debugId}");
|
||||||
|
return (id == -1 || _storage.Length <= id ? null : _storage[id]) ?? throw new NullReferenceException();
|
||||||
|
}
|
||||||
|
|
||||||
private int FindLastIndex()
|
private int FindLastIndex()
|
||||||
{
|
{
|
||||||
for (var i = 0; i < _storage.Length; i++)
|
for (var i = 0; i < _storage.Length; i++)
|
||||||
@@ -106,9 +116,5 @@ namespace mROA.Implementation.Backend
|
|||||||
_storage = nextStorage;
|
_storage = nextStorage;
|
||||||
return _storage.Length;
|
return _storage.Length;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Inject<T>(T dependency)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace mROA.Abstract
|
||||||
|
{
|
||||||
|
public class EventBinder<T> : IEventBinder<T>
|
||||||
|
{
|
||||||
|
public Action<T, IEndPointContext, IRepresentationModuleProducer, int> BindAction { get; set; }
|
||||||
|
|
||||||
|
public void BindEvents(T source, IEndPointContext context,
|
||||||
|
IRepresentationModuleProducer representationModuleProducer, int index)
|
||||||
|
{
|
||||||
|
BindAction(source, context, representationModuleProducer, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -75,8 +75,10 @@ namespace mROA.Implementation.Frontend
|
|||||||
var cancelRequest =
|
var cancelRequest =
|
||||||
_representationModule!.GetMessageAsync<CancelRequest>(
|
_representationModule!.GetMessageAsync<CancelRequest>(
|
||||||
messageType: MessageType.CancelRequest, token: token);
|
messageType: MessageType.CancelRequest, token: token);
|
||||||
|
var eventRequest =
|
||||||
Task.WaitAny(defaultRequest, cancelRequest);
|
_representationModule!.GetMessageAsync<DefaultCallRequest>(
|
||||||
|
messageType: MessageType.EventRequest, token: token);
|
||||||
|
Task.WaitAny(defaultRequest, cancelRequest, eventRequest);
|
||||||
#if TRACE
|
#if TRACE
|
||||||
Console.WriteLine("Request received");
|
Console.WriteLine("Request received");
|
||||||
#endif
|
#endif
|
||||||
@@ -89,7 +91,7 @@ namespace mROA.Implementation.Frontend
|
|||||||
tokenSource.Cancel();
|
tokenSource.Cancel();
|
||||||
_executeModule.Execute(req, _contextRepository, _representationModule);
|
_executeModule.Execute(req, _contextRepository, _representationModule);
|
||||||
}
|
}
|
||||||
else
|
else if (defaultRequest.IsCompleted)
|
||||||
{
|
{
|
||||||
tokenSource.Cancel();
|
tokenSource.Cancel();
|
||||||
var request = defaultRequest.Result;
|
var request = defaultRequest.Result;
|
||||||
@@ -113,6 +115,12 @@ namespace mROA.Implementation.Frontend
|
|||||||
|
|
||||||
_representationModule.PostCallMessage(request.Id, resultType, result, result.GetType());
|
_representationModule.PostCallMessage(request.Id, resultType, result, result.GetType());
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tokenSource.Cancel();
|
||||||
|
var request = defaultRequest.Result;
|
||||||
|
_executeModule.Execute(request, _contextRepository, _representationModule);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
|
|||||||
Reference in New Issue
Block a user