еще один шаг до последнего шага
This commit is contained in:
@@ -8,8 +8,20 @@ namespace Example.Backend;
|
|||||||
[SharedObjectSingleton]
|
[SharedObjectSingleton]
|
||||||
public class PrinterFactory : IPrinterFactory
|
public class PrinterFactory : IPrinterFactory
|
||||||
{
|
{
|
||||||
|
private List<IPrinter> _printers = new();
|
||||||
|
|
||||||
public SharedObject<IPrinter> Create(string printerName)
|
public SharedObject<IPrinter> Create(string printerName)
|
||||||
{
|
{
|
||||||
return new Printer {Name = printerName};
|
return new Printer { Name = printerName };
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Register(SharedObject<IPrinter> printer)
|
||||||
|
{
|
||||||
|
_printers.Add(printer.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SharedObject<IPrinter> GetPrinterByName(string printerName)
|
||||||
|
{
|
||||||
|
return new SharedObject<IPrinter>(_printers.Find(i => i.GetName() == printerName)!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,16 +7,18 @@ using mROA.Implementation.Backend;
|
|||||||
using mROA.Implementation.Bootstrap;
|
using mROA.Implementation.Bootstrap;
|
||||||
|
|
||||||
|
|
||||||
var bootstrap = new FullMixBuilder();
|
var builder = new FullMixBuilder();
|
||||||
bootstrap.UseJsonSerialisation();
|
builder.UseJsonSerialisation();
|
||||||
bootstrap.UseNetworkGateway(new IPEndPoint(IPAddress.Loopback, 4567));
|
builder.UseNetworkGateway(new IPEndPoint(IPAddress.Loopback, 4567));
|
||||||
bootstrap.UseStreamInteraction();
|
builder.UseStreamInteraction();
|
||||||
bootstrap.UseBasicExecution();
|
builder.UseBasicExecution();
|
||||||
bootstrap.UseCollectableContextRepository(typeof(PrinterFactory).Assembly);
|
builder.UseCollectableContextRepository(typeof(PrinterFactory).Assembly);
|
||||||
bootstrap.SetupMethodsRepository(new CoCodegenMethodRepository());
|
builder.SetupMethodsRepository(new CoCodegenMethodRepository());
|
||||||
bootstrap.Build();
|
builder.Modules.Add(new StaticSerialisationModuleProducer());
|
||||||
|
|
||||||
|
builder.Build();
|
||||||
|
|
||||||
|
|
||||||
var gateway = bootstrap.GetModule<IGatewayModule>() ;
|
var gateway = builder.GetModule<IGatewayModule>() ;
|
||||||
|
|
||||||
gateway.Run();
|
gateway.Run();
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
using Example.Shared;
|
||||||
|
using mROA.Implementation;
|
||||||
|
|
||||||
|
namespace Example.Frontend;
|
||||||
|
|
||||||
|
public class ClientBasedPrinter : IPrinter
|
||||||
|
{
|
||||||
|
public string GetName()
|
||||||
|
{
|
||||||
|
return "ClientBasedPrinter";
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<SharedObject<IPage>> Print(string text, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Printed: {text}");
|
||||||
|
await Task.Yield();
|
||||||
|
return new ClientBasedPage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ClientBasedPage : IPage
|
||||||
|
{
|
||||||
|
public byte[] GetData()
|
||||||
|
{
|
||||||
|
return [1, 2, 3];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,9 +4,11 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using Example.Frontend;
|
||||||
using Example.Shared;
|
using Example.Shared;
|
||||||
using mROA.Codegen;
|
using mROA.Codegen;
|
||||||
using mROA.Implementation;
|
using mROA.Implementation;
|
||||||
|
using mROA.Implementation.Backend;
|
||||||
using mROA.Implementation.Bootstrap;
|
using mROA.Implementation.Bootstrap;
|
||||||
using mROA.Implementation.Frontend;
|
using mROA.Implementation.Frontend;
|
||||||
|
|
||||||
@@ -17,22 +19,26 @@ mixer.Modules.Add(new RemoteContextRepository());
|
|||||||
mixer.Modules.Add(new JsonFrontendSerialisationModule());
|
mixer.Modules.Add(new JsonFrontendSerialisationModule());
|
||||||
mixer.Modules.Add(new StreamBasedFrontendInteractionModule());
|
mixer.Modules.Add(new StreamBasedFrontendInteractionModule());
|
||||||
mixer.Modules.Add(new NetworkFrontendBridge(new IPEndPoint(IPAddress.Loopback, 4567)));
|
mixer.Modules.Add(new NetworkFrontendBridge(new IPEndPoint(IPAddress.Loopback, 4567)));
|
||||||
|
mixer.Modules.Add(new StaticSerialisationModuleProducer());
|
||||||
|
mixer.UseCollectableContextRepository();
|
||||||
mixer.Build();
|
mixer.Build();
|
||||||
Thread.CurrentThread.ManagedThreadId
|
|
||||||
TransmissionConfig.RealContextRepository = mixer.GetModule<RemoteContextRepository>();
|
TransmissionConfig.RealContextRepository = mixer.GetModule<ContextRepository>();
|
||||||
TransmissionConfig.RemoteEndpointContextRepository = mixer.GetModule<RemoteContextRepository>();
|
TransmissionConfig.RemoteEndpointContextRepository = mixer.GetModule<RemoteContextRepository>();
|
||||||
mixer.GetModule<NetworkFrontendBridge>().Connect();
|
mixer.GetModule<NetworkFrontendBridge>().Connect();
|
||||||
|
|
||||||
Console.WriteLine(TransmissionConfig.ProcessOwnerId);
|
Console.WriteLine(TransmissionConfig.OwnershipRepository.GetOwnershipId());
|
||||||
var context = mixer.GetModule<RemoteContextRepository>();
|
var context = mixer.GetModule<RemoteContextRepository>();
|
||||||
|
|
||||||
var factory = context.GetSingleObject(typeof(IPrinterFactory)) as IPrinterFactory;
|
var factory = context.GetSingleObject(typeof(IPrinterFactory)) as IPrinterFactory;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var printer = factory.Create("Test");
|
var printer = factory.Create("Test");
|
||||||
var name = printer.Value.GetName();
|
var name = printer.Value.GetName();
|
||||||
Console.WriteLine("Printer name : {0}", name);
|
Console.WriteLine("Printer name : {0}", name);
|
||||||
|
|
||||||
|
factory.Register(new SharedObject<IPrinter>(new ClientBasedPrinter()));
|
||||||
|
|
||||||
var page = await printer.Value.Print("Test Page", new CancellationToken());
|
var page = await printer.Value.Print("Test Page", new CancellationToken());
|
||||||
var data = page.Value.GetData();
|
var data = page.Value.GetData();
|
||||||
Console.WriteLine("Data : {0}", Encoding.UTF8.GetString(data));
|
Console.WriteLine("Data : {0}", Encoding.UTF8.GetString(data));
|
||||||
@@ -46,6 +52,7 @@ for (int i = 0; i < iterations; i++)
|
|||||||
{
|
{
|
||||||
x = loadSingleton.Next(x);
|
x = loadSingleton.Next(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
timer.Stop();
|
timer.Stop();
|
||||||
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);
|
||||||
@@ -8,5 +8,7 @@ namespace Example.Shared;
|
|||||||
public interface IPrinterFactory
|
public interface IPrinterFactory
|
||||||
{
|
{
|
||||||
SharedObject<IPrinter> Create(string printerName);
|
SharedObject<IPrinter> Create(string printerName);
|
||||||
|
void Register(SharedObject<IPrinter> printer);
|
||||||
|
SharedObject<IPrinter> GetPrinterByName(string printerName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -187,6 +187,7 @@ namespace {namespaceName};
|
|||||||
partial class {className} (int id, ISerialisationModule.IFrontendSerialisationModule serialisationModule) : {originalName}, IRemoteObject
|
partial class {className} (int id, ISerialisationModule.IFrontendSerialisationModule serialisationModule) : {originalName}, IRemoteObject
|
||||||
{{
|
{{
|
||||||
public int Id => id;
|
public int Id => id;
|
||||||
|
public int OwnerId => serialisationModule.ClientId;
|
||||||
|
|
||||||
{string.Join("\r\n\t", methodsText)}
|
{string.Join("\r\n\t", methodsText)}
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ public interface IInteractionModule : IInjectableModule
|
|||||||
void RegisterSource(Stream stream);
|
void RegisterSource(Stream stream);
|
||||||
public interface IFrontendInteractionModule : IInjectableModule
|
public interface IFrontendInteractionModule : IInjectableModule
|
||||||
{
|
{
|
||||||
|
int ClientId { get; }
|
||||||
public Task<byte[]> ReceiveMessage();
|
public Task<byte[]> ReceiveMessage();
|
||||||
public void PostMessage(byte[] message);
|
public void PostMessage(byte[] message);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,4 +3,5 @@
|
|||||||
public interface IRemoteObject
|
public interface IRemoteObject
|
||||||
{
|
{
|
||||||
public int Id { get; }
|
public int Id { get; }
|
||||||
|
public int OwnerId { get; }
|
||||||
}
|
}
|
||||||
@@ -9,6 +9,7 @@ public interface ISerialisationModule : IInjectableModule
|
|||||||
void SendWelcomeMessage(int clientId);
|
void SendWelcomeMessage(int clientId);
|
||||||
public interface IFrontendSerialisationModule : IInjectableModule
|
public interface IFrontendSerialisationModule : IInjectableModule
|
||||||
{
|
{
|
||||||
|
int ClientId { get; }
|
||||||
Task<T> GetNextCommandExecution<T>(Guid requestId) where T : ICommandExecution;
|
Task<T> GetNextCommandExecution<T>(Guid requestId) where T : ICommandExecution;
|
||||||
Task<FinalCommandExecution<T>> GetFinalCommandExecution<T>(Guid requestId);
|
Task<FinalCommandExecution<T>> GetFinalCommandExecution<T>(Guid requestId);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
using mROA.Abstract;
|
||||||
|
|
||||||
|
namespace mROA.Implementation;
|
||||||
|
|
||||||
|
interface ISerialisationModuleProducer : IInjectableModule
|
||||||
|
{
|
||||||
|
ISerialisationModule.IFrontendSerialisationModule Produce(int ownership);
|
||||||
|
}
|
||||||
@@ -8,7 +8,7 @@ public class MultiClientOwnershipRepository : IOwnershipRepository
|
|||||||
|
|
||||||
public int GetOwnershipId()
|
public int GetOwnershipId()
|
||||||
{
|
{
|
||||||
return _ownerships.GetValueOrDefault(Environment.CurrentManagedThreadId, -1);
|
return _ownerships.GetValueOrDefault(Environment.CurrentManagedThreadId, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RegisterOwnership(int ownershipId, int threadId)
|
public void RegisterOwnership(int ownershipId, int threadId)
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ public class StreamBasedInteractionModule : IInteractionModule
|
|||||||
|
|
||||||
private async Task ListenTo((int id, Stream stream) client, Action<int, byte[]> action)
|
private async Task ListenTo((int id, Stream stream) client, Action<int, byte[]> action)
|
||||||
{
|
{
|
||||||
|
TransmissionConfig.OwnershipRepository = new MultiClientOwnershipRepository();
|
||||||
const int bufferSize = ushort.MaxValue;
|
const int bufferSize = ushort.MaxValue;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ public class JsonFrontendSerialisationModule
|
|||||||
{
|
{
|
||||||
private IInteractionModule.IFrontendInteractionModule? _interactionModule;
|
private IInteractionModule.IFrontendInteractionModule? _interactionModule;
|
||||||
|
|
||||||
|
public int ClientId => _interactionModule!.ClientId;
|
||||||
|
|
||||||
public async Task<T> GetNextCommandExecution<T>(Guid requestId) where T : ICommandExecution
|
public async Task<T> GetNextCommandExecution<T>(Guid requestId) where T : ICommandExecution
|
||||||
{
|
{
|
||||||
if (_interactionModule is null)
|
if (_interactionModule is null)
|
||||||
|
|||||||
@@ -6,11 +6,13 @@ public class StreamBasedFrontendInteractionModule : IInteractionModule.IFrontend
|
|||||||
{
|
{
|
||||||
public Stream? ServerStream { get; set; }
|
public Stream? ServerStream { get; set; }
|
||||||
|
|
||||||
|
public int ClientId { get; set; }
|
||||||
|
|
||||||
public async Task<byte[]> ReceiveMessage()
|
public async Task<byte[]> ReceiveMessage()
|
||||||
{
|
{
|
||||||
if (ServerStream is null)
|
if (ServerStream is null)
|
||||||
throw new IOException("Server is not connected.");
|
throw new IOException("Server is not connected.");
|
||||||
|
|
||||||
const int bufferSize = ushort.MaxValue;
|
const int bufferSize = ushort.MaxValue;
|
||||||
|
|
||||||
var buffer = new byte[bufferSize];
|
var buffer = new byte[bufferSize];
|
||||||
@@ -27,12 +29,12 @@ public class StreamBasedFrontendInteractionModule : IInteractionModule.IFrontend
|
|||||||
{
|
{
|
||||||
if (ServerStream is null)
|
if (ServerStream is null)
|
||||||
throw new IOException("Server is not connected.");
|
throw new IOException("Server is not connected.");
|
||||||
|
|
||||||
ServerStream.Write(BitConverter.GetBytes((ushort)message.Length), 0, sizeof(ushort));
|
ServerStream.Write(BitConverter.GetBytes((ushort)message.Length), 0, sizeof(ushort));
|
||||||
ServerStream.Write(message, 0, message.Length);
|
ServerStream.Write(message, 0, message.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Inject<T>(T dependency)
|
public void Inject<T>(T dependency)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -6,7 +6,8 @@ namespace mROA.Implementation;
|
|||||||
|
|
||||||
public class RemoteContextRepository : IContextRepository
|
public class RemoteContextRepository : IContextRepository
|
||||||
{
|
{
|
||||||
private ISerialisationModule.IFrontendSerialisationModule _serialisationModule;
|
private ISerialisationModuleProducer _serialisationModule;
|
||||||
|
private ISerialisationModuleProducer _producer;
|
||||||
public static FrozenDictionary<Type, Type> RemoteTypes;
|
public static FrozenDictionary<Type, Type> RemoteTypes;
|
||||||
public int ResisterObject(object o)
|
public int ResisterObject(object o)
|
||||||
{
|
{
|
||||||
@@ -27,7 +28,7 @@ public class RemoteContextRepository : IContextRepository
|
|||||||
{
|
{
|
||||||
if (RemoteTypes.TryGetValue(typeof(T), out var remoteType))
|
if (RemoteTypes.TryGetValue(typeof(T), out var remoteType))
|
||||||
{
|
{
|
||||||
var remote = (T)Activator.CreateInstance(remoteType, id, _serialisationModule)!;
|
var remote = (T)Activator.CreateInstance(remoteType, id, _serialisationModule.Produce(TransmissionConfig.OwnershipRepository.GetOwnershipId()))!;
|
||||||
return remote;
|
return remote;
|
||||||
}
|
}
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
@@ -35,7 +36,7 @@ public class RemoteContextRepository : IContextRepository
|
|||||||
|
|
||||||
public object GetSingleObject(Type type)
|
public object GetSingleObject(Type type)
|
||||||
{
|
{
|
||||||
return Activator.CreateInstance(RemoteTypes[type], -1, _serialisationModule)!;
|
return Activator.CreateInstance(RemoteTypes[type], -1, _serialisationModule.Produce(TransmissionConfig.OwnershipRepository.GetOwnershipId()))!;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetObjectIndex(object o)
|
public int GetObjectIndex(object o)
|
||||||
@@ -49,7 +50,7 @@ public class RemoteContextRepository : IContextRepository
|
|||||||
|
|
||||||
public void Inject<T>(T dependency)
|
public void Inject<T>(T dependency)
|
||||||
{
|
{
|
||||||
if (dependency is ISerialisationModule.IFrontendSerialisationModule serialisationModule)
|
if (dependency is ISerialisationModuleProducer serialisationModule)
|
||||||
_serialisationModule = serialisationModule;
|
_serialisationModule = serialisationModule;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8,7 +8,6 @@ public static class TransmissionConfig
|
|||||||
public static IContextRepository? RealContextRepository { get; set; }
|
public static IContextRepository? RealContextRepository { get; set; }
|
||||||
public static IContextRepository? RemoteEndpointContextRepository { get; set; }
|
public static IContextRepository? RemoteEndpointContextRepository { get; set; }
|
||||||
public static IOwnershipRepository? OwnershipRepository { get; set; }
|
public static IOwnershipRepository? OwnershipRepository { get; set; }
|
||||||
public static Dictionary<int, int> ThreadsOwners { get; } = new();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SharedObject<T> where T : notnull
|
public class SharedObject<T> where T : notnull
|
||||||
@@ -41,7 +40,8 @@ public class SharedObject<T> where T : notnull
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[JsonIgnore] public T Value { get; private set; }
|
[JsonIgnore]
|
||||||
|
public T Value { get; private set; }
|
||||||
|
|
||||||
// ReSharper disable once MemberCanBePrivate.Global
|
// ReSharper disable once MemberCanBePrivate.Global
|
||||||
public SharedObject()
|
public SharedObject()
|
||||||
@@ -52,16 +52,23 @@ public class SharedObject<T> where T : notnull
|
|||||||
public SharedObject(T value)
|
public SharedObject(T value)
|
||||||
{
|
{
|
||||||
Value = value;
|
Value = value;
|
||||||
_contextId = GetDefaultContextRepository().GetObjectIndex(value);
|
|
||||||
|
if (value is IRemoteObject ro)
|
||||||
|
{
|
||||||
|
_ownerId = ro.OwnerId;
|
||||||
|
_contextId = ro.Id;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_contextId = TransmissionConfig.RealContextRepository!.GetObjectIndex(value);
|
||||||
|
_ownerId = TransmissionConfig.OwnershipRepository!.GetOwnershipId();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static implicit operator T(SharedObject<T> value) => value.Value;
|
public static implicit operator T(SharedObject<T> value) => value.Value;
|
||||||
|
|
||||||
public static implicit operator SharedObject<T>(T value) =>
|
public static implicit operator SharedObject<T>(T value) =>
|
||||||
new()
|
new(value);
|
||||||
{
|
|
||||||
ContextId = value is IRemoteObject ro
|
|
||||||
? TransmissionConfig.RemoteEndpointContextRepository!.GetObjectIndex(ro)
|
|
||||||
: TransmissionConfig.RealContextRepository!.GetObjectIndex(value)
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using mROA.Abstract;
|
||||||
|
|
||||||
|
namespace mROA.Implementation;
|
||||||
|
|
||||||
|
public class StaticSerialisationModuleProducer : ISerialisationModuleProducer
|
||||||
|
{
|
||||||
|
private ISerialisationModule.IFrontendSerialisationModule _serialisationModule;
|
||||||
|
|
||||||
|
public ISerialisationModule.IFrontendSerialisationModule Produce(int ownership)
|
||||||
|
{
|
||||||
|
return _serialisationModule;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Inject<T>(T dependency)
|
||||||
|
{
|
||||||
|
if (dependency is ISerialisationModule.IFrontendSerialisationModule serialisationModule)
|
||||||
|
_serialisationModule = serialisationModule;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user