This commit is contained in:
Jonathan Goldstein 2018-12-06 15:51:24 -08:00
Родитель ac0c47b7d0 995a49d779
Коммит 19733d0e00
18 изменённых файлов: 590 добавлений и 39 удалений

Просмотреть файл

@ -1,5 +1,5 @@
using Ambrosia;
using IClient;
using IClient1;
using IServer;
using Microsoft.VisualStudio.Threading;
using System;
@ -9,7 +9,7 @@ using System.Threading.Tasks;
namespace Client1
{
[DataContract]
class Client1 : Immortal<IClientProxy>, IClient.IClient
class Client1 : Immortal<IClient1Proxy>, IClient1.IClient1
{
[DataMember]
private string _serverName;
@ -50,7 +50,7 @@ namespace Client1
string clientInstanceName = "client1";
string serverInstanceName = "server1";
using (var c = AmbrosiaFactory.Deploy<IClient.IClient>(clientInstanceName, new Client1(serverInstanceName), receivePort, sendPort))
using (var c = AmbrosiaFactory.Deploy<IClient1.IClient1>(clientInstanceName, new Client1(serverInstanceName), receivePort, sendPort))
{
finishedTokenQ.DequeueAsync().Wait();
}

Просмотреть файл

@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AmbrosiaLibCS" Version="2018.12.6.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\GeneratedSourceFiles\Client2Interfaces\latest\Client2Interfaces.csproj" />
<ProjectReference Include="..\GeneratedSourceFiles\ServerInterfaces\latest\ServerInterfaces.csproj" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,77 @@
using System;
using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
using Ambrosia;
using IClient2;
using IServer;
using Microsoft.VisualStudio.Threading;
namespace Client2
{
[DataContract]
class Client2 : Immortal<IClient2Proxy>, IClient2.IClient2
{
[DataMember]
private string _serverName;
[DataMember]
private IServerProxy _server;
public Client2(string serverName)
{
_serverName = serverName;
}
public void IngressKeyboardInput(string input)
{
thisProxy.ReceiveKeyboardInputFork(input);
}
public async Task ReceiveKeyboardInputAsync(string input)
{
await thisProxy.SendMessageAsync(input);
}
public async Task SendMessageAsync(string message)
{
Console.WriteLine("Sending message to server: " + message);
int numMessages = await _server.ReceiveMessageAsync(message);
Console.WriteLine("Sent message to server! Server has received " + numMessages + " messages.");
}
protected override async Task<bool> OnFirstStart()
{
_server = GetProxy<IServerProxy>(_serverName);
return true;
}
}
class Program
{
public static AsyncQueue<int> finishedTokenQ;
static void Main(string[] args)
{
finishedTokenQ = new AsyncQueue<int>();
int receivePort = 1001;
int sendPort = 1000;
string clientInstanceName = "client2";
string serverInstanceName = "server1";
Client2 client = new Client2(serverInstanceName);
using (var c = AmbrosiaFactory.Deploy<IClient2.IClient2>(clientInstanceName, client, receivePort, sendPort))
{
while (finishedTokenQ.IsEmpty)
{
Console.Write("Enter a message (hit ENTER to send): ");
string input = Console.ReadLine();
client.IngressKeyboardInput(input);
Thread.Sleep(1000);
}
finishedTokenQ.DequeueAsync().Wait();
}
}
}
}

Просмотреть файл

@ -14,8 +14,11 @@ Write-Host "Using variant of CodeGen.exe: $env:AMBVARIANT"
Write-Host "Executing codegen command: dotnet $ambrosiaPath\Clients\CSharp\AmbrosiaCS\bin\$env:AMBVARIANT\AmbrosiaCS.dll CodeGen -a=ServerAPI\bin\$env:AMBVARIANT\IServer.dll -o=ServerInterfaces -f=netcoreapp2.0 -b=CodeGenDependencies\netcoreapp2.0"
Write-Host "Executing codegen command: dotnet $ambrosiaPath\Clients\CSharp\AmbrosiaCS\bin\$env:AMBVARIANT\AmbrosiaCS.dll CodeGen -a=IClient\bin\$env:AMBVARIANT\IClient.dll -o=Client1Interfaces -f=netcoreapp2.0 -b=CodeGenDependencies\netcoreapp2.0"
Write-Host "Executing codegen command: dotnet $ambrosiaPath\Clients\CSharp\AmbrosiaCS\bin\$env:AMBVARIANT\AmbrosiaCS.dll CodeGen -a=IClient1\bin\$env:AMBVARIANT\IClient1.dll -o=Client1Interfaces -f=netcoreapp2.0 -b=CodeGenDependencies\netcoreapp2.0"
Write-Host "Executing codegen command: dotnet $ambrosiaPath\Clients\CSharp\AmbrosiaCS\bin\$env:AMBVARIANT\AmbrosiaCS.dll CodeGen -a=IClient2\bin\$env:AMBVARIANT\IClient2.dll -o=Client2Interfaces -f=netcoreapp2.0 -b=CodeGenDependencies\netcoreapp2.0"
# Generate the assemblies, assumes an .exe which is created by a .Net Framework build:
& dotnet $ambrosiaPath\Clients\CSharp\AmbrosiaCS\bin\$env:AMBVARIANT\AmbrosiaCS.dll CodeGen -a="ServerAPI\bin\$env:AMBVARIANT\IServer.dll" -o=ServerInterfaces -f="netcoreapp2.0" -b="CodeGenDependencies\netcoreapp2.0"
& dotnet $ambrosiaPath\Clients\CSharp\AmbrosiaCS\bin\$env:AMBVARIANT\AmbrosiaCS.dll CodeGen -a="IClient\bin\$env:AMBVARIANT\IClient.dll" -o=Client1Interfaces -f="netcoreapp2.0" -b="CodeGenDependencies\netcoreapp2.0"
& dotnet $ambrosiaPath\Clients\CSharp\AmbrosiaCS\bin\$env:AMBVARIANT\AmbrosiaCS.dll CodeGen -a="IClient1\bin\$env:AMBVARIANT\IClient1.dll" -o=Client1Interfaces -f="netcoreapp2.0" -b="CodeGenDependencies\netcoreapp2.0"
& dotnet $ambrosiaPath\Clients\CSharp\AmbrosiaCS\bin\$env:AMBVARIANT\AmbrosiaCS.dll CodeGen -a="IClient2\bin\$env:AMBVARIANT\IClient2.dll" -o=Client2Interfaces -f="netcoreapp2.0" -b="CodeGenDependencies\netcoreapp2.0"

Просмотреть файл

@ -6,29 +6,29 @@ using Ambrosia;
using static Ambrosia.StreamCommunicator;
using LocalAmbrosiaRuntime;
namespace IClient
namespace IClient1
{
/// <summary>
/// This class runs in the process of the object that implements the interface IClient
/// This class runs in the process of the object that implements the interface IClient1
/// and communicates with the local Ambrosia runtime.
/// It is instantiated in ImmortalFactory.CreateServer when a bootstrapper registers a container
/// that supports the interface IClient.
/// that supports the interface IClient1.
/// </summary>
class IClient_Dispatcher_Implementation : Immortal.Dispatcher
class IClient1_Dispatcher_Implementation : Immortal.Dispatcher
{
private readonly IClient instance;
private readonly IClient1 instance;
private readonly ExceptionSerializer exceptionSerializer = new ExceptionSerializer(new List<Type>());
public IClient_Dispatcher_Implementation(Immortal z, ImmortalSerializerBase myImmortalSerializer, string serviceName, int receivePort, int sendPort, bool setupConnections)
public IClient1_Dispatcher_Implementation(Immortal z, ImmortalSerializerBase myImmortalSerializer, string serviceName, int receivePort, int sendPort, bool setupConnections)
: base(z, myImmortalSerializer, serviceName, receivePort, sendPort, setupConnections)
{
this.instance = (IClient) z;
this.instance = (IClient1) z;
}
public IClient_Dispatcher_Implementation(Immortal z, ImmortalSerializerBase myImmortalSerializer, string localAmbrosiaRuntime, Type newInterface, Type newImmortalType, int receivePort, int sendPort)
public IClient1_Dispatcher_Implementation(Immortal z, ImmortalSerializerBase myImmortalSerializer, string localAmbrosiaRuntime, Type newInterface, Type newImmortalType, int receivePort, int sendPort)
: base(z, myImmortalSerializer, localAmbrosiaRuntime, newInterface, newImmortalType, receivePort, sendPort)
{
this.instance = (IClient) z;
this.instance = (IClient1) z;
}
public override async Task<bool> DispatchToMethod(int methodId, RpcTypes.RpcType rpcType, string senderOfRPC, long sequenceNumber, byte[] buffer, int cursor)

Просмотреть файл

@ -10,7 +10,7 @@ using System.Xml;
using Ambrosia;
using static Ambrosia.StreamCommunicator;
using IClient;
using IClient1;
namespace Ambrosia
{
@ -23,7 +23,7 @@ namespace Ambrosia
{
base.KnownTypes = new SerializableType[]
{
new SerializableType(typeof(IClientProxy_Implementation)),
new SerializableType(typeof(IClient1Proxy_Implementation)),
new SerializableType(this.GetType())
};
}

Просмотреть файл

@ -4,23 +4,23 @@ using Ambrosia;
using System.Threading.Tasks;
using static Ambrosia.StreamCommunicator;
namespace IClient
namespace IClient1
{
/// <summary>
// Generated from IClient by the proxy generation.
// Generated from IClient1 by the proxy generation.
// This is the API that any immortal implementing the interface must be a subtype of.
/// </summary>
public interface IClient
public interface IClient1
{
Task SendMessageAsync(System.String p_0);
}
/// <summary>
// Generated from IClient by the proxy generation.
// Generated from IClient1 by the proxy generation.
// This is the API that is used to call a immortal that implements
/// </summary>
[Ambrosia.InstanceProxy(typeof(IClient))]
public interface IClientProxy
[Ambrosia.InstanceProxy(typeof(IClient1))]
public interface IClient1Proxy
{
Task SendMessageAsync(System.String p_0);
void SendMessageFork(System.String p_0);

Просмотреть файл

@ -6,24 +6,24 @@ using Ambrosia;
using static Ambrosia.StreamCommunicator;
namespace IClient
namespace IClient1
{
/// <summary>
/// This class is the proxy that runs in the client's process and communicates with the local Ambrosia runtime.
/// It runs within the client's process, so it is generated in the language that the client is using.
/// It is returned from ImmortalFactory.CreateClient when a client requests a container that supports the interface IClientProxy.
/// It is returned from ImmortalFactory.CreateClient when a client requests a container that supports the interface IClient1Proxy.
/// </summary>
[System.Runtime.Serialization.DataContract]
public class IClientProxy_Implementation : Immortal.InstanceProxy, IClientProxy
public class IClient1Proxy_Implementation : Immortal.InstanceProxy, IClient1Proxy
{
public IClientProxy_Implementation(string remoteAmbrosiaRuntime, bool attachNeeded)
public IClient1Proxy_Implementation(string remoteAmbrosiaRuntime, bool attachNeeded)
: base(remoteAmbrosiaRuntime, attachNeeded)
{
}
async Task
IClientProxy.SendMessageAsync(System.String p_0)
IClient1Proxy.SendMessageAsync(System.String p_0)
{
await SendMessageAsync(p_0);
}
@ -75,7 +75,7 @@ wp.curLength += arg0Bytes.Length;
return;
}
void IClientProxy.SendMessageFork(System.String p_0)
void IClient1Proxy.SendMessageFork(System.String p_0)
{
SerializableTaskCompletionSource rpcTask;

Просмотреть файл

@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
</ItemGroup>
<ItemGroup>
<PackageReference Include="AmbrosiaLibCS" Version="2018.11.30.1" />
<PackageReference Include="Mono.Options.Core" Version="1.0.0" />
<PackageReference Include="System.Runtime.Serialization.Primitives" Version="4.3.0" />
<PackageReference Include="System.Threading.Tasks.Dataflow" Version="4.9.0" />
<PackageReference Update="Microsoft.NETCore.App=" Version="2.0.0=" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,125 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Ambrosia;
using static Ambrosia.StreamCommunicator;
using LocalAmbrosiaRuntime;
namespace IClient2
{
/// <summary>
/// This class runs in the process of the object that implements the interface IClient2
/// and communicates with the local Ambrosia runtime.
/// It is instantiated in ImmortalFactory.CreateServer when a bootstrapper registers a container
/// that supports the interface IClient2.
/// </summary>
class IClient2_Dispatcher_Implementation : Immortal.Dispatcher
{
private readonly IClient2 instance;
private readonly ExceptionSerializer exceptionSerializer = new ExceptionSerializer(new List<Type>());
public IClient2_Dispatcher_Implementation(Immortal z, ImmortalSerializerBase myImmortalSerializer, string serviceName, int receivePort, int sendPort, bool setupConnections)
: base(z, myImmortalSerializer, serviceName, receivePort, sendPort, setupConnections)
{
this.instance = (IClient2) z;
}
public IClient2_Dispatcher_Implementation(Immortal z, ImmortalSerializerBase myImmortalSerializer, string localAmbrosiaRuntime, Type newInterface, Type newImmortalType, int receivePort, int sendPort)
: base(z, myImmortalSerializer, localAmbrosiaRuntime, newInterface, newImmortalType, receivePort, sendPort)
{
this.instance = (IClient2) z;
}
public override async Task<bool> DispatchToMethod(int methodId, RpcTypes.RpcType rpcType, string senderOfRPC, long sequenceNumber, byte[] buffer, int cursor)
{
switch (methodId)
{
case 0:
// Entry point
this.EntryPoint();
break;
case 1:
// SendMessageAsync
{
// deserialize arguments
// arg0: System.String
var p_0_ValueLength = buffer.ReadBufferedInt(cursor);
cursor += IntSize(p_0_ValueLength);
var p_0_ValueBuffer = new byte[p_0_ValueLength];
Buffer.BlockCopy(buffer, cursor, p_0_ValueBuffer, 0, p_0_ValueLength);
cursor += p_0_ValueLength;
var p_0 = Ambrosia.BinarySerializer.Deserialize<System.String>(p_0_ValueBuffer);
// call the method
byte[] argExBytes = null;
int argExSize = 0;
Exception currEx = null;
int arg1Size = 0;
byte[] arg1Bytes = null;
try
{
await this.instance.SendMessageAsync(p_0);
}
catch (Exception ex)
{
currEx = ex;
}
if (!rpcType.IsFireAndForget())
{
// serialize result and send it back (there isn't one)
arg1Size = 0;
var wp = this.StartRPC_ReturnValue(senderOfRPC, sequenceNumber, currEx == null ? arg1Size : argExSize, currEx == null ? ReturnValueTypes.EmptyReturnValue : ReturnValueTypes.Exception);
this.ReleaseBufferAndSend();
}
}
break;
case 2:
// ReceiveKeyboardInputAsync
{
// deserialize arguments
// arg0: System.String
var p_0_ValueLength = buffer.ReadBufferedInt(cursor);
cursor += IntSize(p_0_ValueLength);
var p_0_ValueBuffer = new byte[p_0_ValueLength];
Buffer.BlockCopy(buffer, cursor, p_0_ValueBuffer, 0, p_0_ValueLength);
cursor += p_0_ValueLength;
var p_0 = Ambrosia.BinarySerializer.Deserialize<System.String>(p_0_ValueBuffer);
// call the method
byte[] argExBytes = null;
int argExSize = 0;
Exception currEx = null;
int arg1Size = 0;
byte[] arg1Bytes = null;
try
{
await this.instance.ReceiveKeyboardInputAsync(p_0);
}
catch (Exception ex)
{
currEx = ex;
}
if (!rpcType.IsFireAndForget())
{
// serialize result and send it back (there isn't one)
arg1Size = 0;
var wp = this.StartRPC_ReturnValue(senderOfRPC, sequenceNumber, currEx == null ? arg1Size : argExSize, currEx == null ? ReturnValueTypes.EmptyReturnValue : ReturnValueTypes.Exception);
this.ReleaseBufferAndSend();
}
}
break;
}
return true;
}
}
}

Просмотреть файл

@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
using System.Xml;
using Ambrosia;
using static Ambrosia.StreamCommunicator;
using IClient2;
namespace Ambrosia
{
/// <summary>
/// This class is the serializer that supports serialization of a Immortal and has the generated classes as a known types
/// </summary>]
public class ImmortalSerializer : ImmortalSerializerBase
{
public ImmortalSerializer()
{
base.KnownTypes = new SerializableType[]
{
new SerializableType(typeof(IClient2Proxy_Implementation)),
new SerializableType(this.GetType())
};
}
public override long SerializeSize(Immortal c)
{
var serializer = new DataContractSerializer(c.GetType(), this.KnownTypes.Select(kt => kt.Type).ToArray());
long retVal = -1;
using (var countStream = new CountStream())
{
using (var writer = XmlDictionaryWriter.CreateBinaryWriter(countStream))
{
serializer.WriteObject(writer, c);
}
retVal = countStream.Length;
}
return retVal;
}
public override void Serialize(Immortal c, Stream writeToStream)
{
// nned to create
var serializer = new DataContractSerializer(c.GetType(), this.KnownTypes.Select(kt => kt.Type).ToArray());
using (var writer = XmlDictionaryWriter.CreateBinaryWriter(writeToStream))
{
serializer.WriteObject(writer, c);
}
}
public override Immortal Deserialize(Type runtimeType, Stream stream)
{
var serializer = new DataContractSerializer(runtimeType, this.KnownTypes.Select(kt => kt.Type).ToArray());
using (var reader = XmlDictionaryReader.CreateBinaryReader(stream, XmlDictionaryReaderQuotas.Max))
{
return (Immortal)serializer.ReadObject(reader);
}
}
}
public interface Empty : IEmpty
{
}
}

Просмотреть файл

@ -0,0 +1,30 @@
using System;
using Ambrosia;
using System.Threading.Tasks;
using static Ambrosia.StreamCommunicator;
namespace IClient2
{
/// <summary>
// Generated from IClient2 by the proxy generation.
// This is the API that any immortal implementing the interface must be a subtype of.
/// </summary>
public interface IClient2
{
Task SendMessageAsync(System.String p_0);
Task ReceiveKeyboardInputAsync(System.String p_0);
}
/// <summary>
// Generated from IClient2 by the proxy generation.
// This is the API that is used to call a immortal that implements
/// </summary>
[Ambrosia.InstanceProxy(typeof(IClient2))]
public interface IClient2Proxy
{
Task SendMessageAsync(System.String p_0);
void SendMessageFork(System.String p_0);
void ReceiveKeyboardInputFork(System.String p_0);
}
}

Просмотреть файл

@ -0,0 +1,156 @@
using System;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
using Ambrosia;
using static Ambrosia.StreamCommunicator;
namespace IClient2
{
/// <summary>
/// This class is the proxy that runs in the client's process and communicates with the local Ambrosia runtime.
/// It runs within the client's process, so it is generated in the language that the client is using.
/// It is returned from ImmortalFactory.CreateClient when a client requests a container that supports the interface IClient2Proxy.
/// </summary>
[System.Runtime.Serialization.DataContract]
public class IClient2Proxy_Implementation : Immortal.InstanceProxy, IClient2Proxy
{
public IClient2Proxy_Implementation(string remoteAmbrosiaRuntime, bool attachNeeded)
: base(remoteAmbrosiaRuntime, attachNeeded)
{
}
async Task
IClient2Proxy.SendMessageAsync(System.String p_0)
{
await SendMessageAsync(p_0);
}
async Task
SendMessageAsync(System.String p_0)
{
SerializableTaskCompletionSource rpcTask;
// Make call, wait for reply
// Compute size of serialized arguments
var totalArgSize = 0;
int arg0Size = 0;
byte[] arg0Bytes = null;
// Argument 0
arg0Bytes = Ambrosia.BinarySerializer.Serialize<System.String>(p_0);
arg0Size = IntSize(arg0Bytes.Length) + arg0Bytes.Length;
totalArgSize += arg0Size;
var wp = this.StartRPC<object>(methodIdentifier: 1 /* method identifier for SendMessage */, lengthOfSerializedArguments: totalArgSize, taskToWaitFor: out rpcTask);
var asyncContext = new AsyncContext { SequenceNumber = Immortal.CurrentSequenceNumber };
// Serialize arguments
// Serialize arg0
wp.curLength += wp.PageBytes.WriteInt(wp.curLength, arg0Bytes.Length);
Buffer.BlockCopy(arg0Bytes, 0, wp.PageBytes, wp.curLength, arg0Bytes.Length);
wp.curLength += arg0Bytes.Length;
ReleaseBufferAndSend();
var taskToWaitFor = Immortal.CallCache.Data[asyncContext.SequenceNumber].GetAwaitableTaskWithAdditionalInfoAsync();
var currentResult = await taskToWaitFor;
var isSaved = await Immortal.TrySaveContextContinuationAsync(currentResult);
if (isSaved)
{
taskToWaitFor = Immortal.CallCache.Data[asyncContext.SequenceNumber].GetAwaitableTaskWithAdditionalInfoAsync();
currentResult = await taskToWaitFor;
}
await Immortal.TryTakeCheckpointContinuationAsync(currentResult);
return;
}
void IClient2Proxy.SendMessageFork(System.String p_0)
{
SerializableTaskCompletionSource rpcTask;
// Compute size of serialized arguments
var totalArgSize = 0;
// Argument 0
int arg0Size = 0;
byte[] arg0Bytes = null;
arg0Bytes = Ambrosia.BinarySerializer.Serialize<System.String>(p_0);
arg0Size = IntSize(arg0Bytes.Length) + arg0Bytes.Length;
totalArgSize += arg0Size;
var wp = this.StartRPC<object>(1 /* method identifier for SendMessage */, totalArgSize, out rpcTask, RpcTypes.RpcType.FireAndForget);
// Serialize arguments
// Serialize arg0
wp.curLength += wp.PageBytes.WriteInt(wp.curLength, arg0Bytes.Length);
Buffer.BlockCopy(arg0Bytes, 0, wp.PageBytes, wp.curLength, arg0Bytes.Length);
wp.curLength += arg0Bytes.Length;
this.ReleaseBufferAndSend();
return;
}
private object
SendMessage_ReturnValue(byte[] buffer, int cursor)
{
// buffer will be an empty byte array since the method SendMessage returns void
// so nothing to read, just getting called is the signal to return to the client
return this;
}
void IClient2Proxy.ReceiveKeyboardInputFork(System.String p_0)
{
SerializableTaskCompletionSource rpcTask;
// Compute size of serialized arguments
var totalArgSize = 0;
// Argument 0
int arg0Size = 0;
byte[] arg0Bytes = null;
arg0Bytes = Ambrosia.BinarySerializer.Serialize<System.String>(p_0);
arg0Size = IntSize(arg0Bytes.Length) + arg0Bytes.Length;
totalArgSize += arg0Size;
var wp = this.StartRPC<object>(2 /* method identifier for ReceiveKeyboardInput */, totalArgSize, out rpcTask, RpcTypes.RpcType.Impulse);
// Serialize arguments
// Serialize arg0
wp.curLength += wp.PageBytes.WriteInt(wp.curLength, arg0Bytes.Length);
Buffer.BlockCopy(arg0Bytes, 0, wp.PageBytes, wp.curLength, arg0Bytes.Length);
wp.curLength += arg0Bytes.Length;
this.ReleaseBufferAndSend();
return;
}
private object
ReceiveKeyboardInput_ReturnValue(byte[] buffer, int cursor)
{
// buffer will be an empty byte array since the method ReceiveKeyboardInput returns void
// so nothing to read, just getting called is the signal to return to the client
return this;
}
}
}

Просмотреть файл

@ -13,7 +13,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ServerInterfaces", "Generat
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client1Interfaces", "GeneratedSourceFiles\Client1Interfaces\latest\Client1Interfaces.csproj", "{625A71B0-DA9E-467F-9744-A4344EA8B6E5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IClient", "IClient\IClient.csproj", "{F07FF1A8-5617-4C43-B70A-14A4C8D57EDB}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IClient2", "IClient2\IClient2.csproj", "{975C3389-6CE2-4905-BE58-57FCF29B5D31}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client2", "Client2\Client2.csproj", "{644D897D-1311-4073-9F0C-4197A9719E28}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client2Interfaces", "GeneratedSourceFiles\Client2Interfaces\latest\Client2Interfaces.csproj", "{6E5C78F0-B847-4C22-90B6-FAA96C013609}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IClient1", "IClient1\IClient1.csproj", "{8EFAD205-E2BF-46C0-B310-7D023210797F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -57,14 +63,38 @@ Global
{625A71B0-DA9E-467F-9744-A4344EA8B6E5}.Release|Any CPU.Build.0 = Release|Any CPU
{625A71B0-DA9E-467F-9744-A4344EA8B6E5}.Release|x64.ActiveCfg = Release|Any CPU
{625A71B0-DA9E-467F-9744-A4344EA8B6E5}.Release|x64.Build.0 = Release|Any CPU
{F07FF1A8-5617-4C43-B70A-14A4C8D57EDB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F07FF1A8-5617-4C43-B70A-14A4C8D57EDB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F07FF1A8-5617-4C43-B70A-14A4C8D57EDB}.Debug|x64.ActiveCfg = Debug|x64
{F07FF1A8-5617-4C43-B70A-14A4C8D57EDB}.Debug|x64.Build.0 = Debug|x64
{F07FF1A8-5617-4C43-B70A-14A4C8D57EDB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F07FF1A8-5617-4C43-B70A-14A4C8D57EDB}.Release|Any CPU.Build.0 = Release|Any CPU
{F07FF1A8-5617-4C43-B70A-14A4C8D57EDB}.Release|x64.ActiveCfg = Release|Any CPU
{F07FF1A8-5617-4C43-B70A-14A4C8D57EDB}.Release|x64.Build.0 = Release|Any CPU
{975C3389-6CE2-4905-BE58-57FCF29B5D31}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{975C3389-6CE2-4905-BE58-57FCF29B5D31}.Debug|Any CPU.Build.0 = Debug|Any CPU
{975C3389-6CE2-4905-BE58-57FCF29B5D31}.Debug|x64.ActiveCfg = Debug|x64
{975C3389-6CE2-4905-BE58-57FCF29B5D31}.Debug|x64.Build.0 = Debug|x64
{975C3389-6CE2-4905-BE58-57FCF29B5D31}.Release|Any CPU.ActiveCfg = Release|Any CPU
{975C3389-6CE2-4905-BE58-57FCF29B5D31}.Release|Any CPU.Build.0 = Release|Any CPU
{975C3389-6CE2-4905-BE58-57FCF29B5D31}.Release|x64.ActiveCfg = Release|Any CPU
{975C3389-6CE2-4905-BE58-57FCF29B5D31}.Release|x64.Build.0 = Release|Any CPU
{644D897D-1311-4073-9F0C-4197A9719E28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{644D897D-1311-4073-9F0C-4197A9719E28}.Debug|Any CPU.Build.0 = Debug|Any CPU
{644D897D-1311-4073-9F0C-4197A9719E28}.Debug|x64.ActiveCfg = Debug|x64
{644D897D-1311-4073-9F0C-4197A9719E28}.Debug|x64.Build.0 = Debug|x64
{644D897D-1311-4073-9F0C-4197A9719E28}.Release|Any CPU.ActiveCfg = Release|Any CPU
{644D897D-1311-4073-9F0C-4197A9719E28}.Release|Any CPU.Build.0 = Release|Any CPU
{644D897D-1311-4073-9F0C-4197A9719E28}.Release|x64.ActiveCfg = Release|Any CPU
{644D897D-1311-4073-9F0C-4197A9719E28}.Release|x64.Build.0 = Release|Any CPU
{6E5C78F0-B847-4C22-90B6-FAA96C013609}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6E5C78F0-B847-4C22-90B6-FAA96C013609}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6E5C78F0-B847-4C22-90B6-FAA96C013609}.Debug|x64.ActiveCfg = Debug|Any CPU
{6E5C78F0-B847-4C22-90B6-FAA96C013609}.Debug|x64.Build.0 = Debug|Any CPU
{6E5C78F0-B847-4C22-90B6-FAA96C013609}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6E5C78F0-B847-4C22-90B6-FAA96C013609}.Release|Any CPU.Build.0 = Release|Any CPU
{6E5C78F0-B847-4C22-90B6-FAA96C013609}.Release|x64.ActiveCfg = Release|Any CPU
{6E5C78F0-B847-4C22-90B6-FAA96C013609}.Release|x64.Build.0 = Release|Any CPU
{8EFAD205-E2BF-46C0-B310-7D023210797F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8EFAD205-E2BF-46C0-B310-7D023210797F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8EFAD205-E2BF-46C0-B310-7D023210797F}.Debug|x64.ActiveCfg = Debug|x64
{8EFAD205-E2BF-46C0-B310-7D023210797F}.Debug|x64.Build.0 = Debug|x64
{8EFAD205-E2BF-46C0-B310-7D023210797F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8EFAD205-E2BF-46C0-B310-7D023210797F}.Release|Any CPU.Build.0 = Release|Any CPU
{8EFAD205-E2BF-46C0-B310-7D023210797F}.Release|x64.ActiveCfg = Release|x64
{8EFAD205-E2BF-46C0-B310-7D023210797F}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

Просмотреть файл

@ -1,8 +1,8 @@
using System;
namespace IClient
namespace IClient1
{
public interface IClient
public interface IClient1
{
void SendMessage(string message);
}

Просмотреть файл

@ -3,6 +3,8 @@
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
<Platforms>AnyCPU;x64</Platforms>
<AssemblyName>IClient1</AssemblyName>
<RootNamespace>IClient1</RootNamespace>
</PropertyGroup>
</Project>

Просмотреть файл

@ -0,0 +1,13 @@
using Ambrosia;
using System;
namespace IClient2
{
public interface IClient2
{
void SendMessage(string message);
[ImpulseHandler]
void ReceiveKeyboardInput(string message);
}
}

Просмотреть файл

@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AmbrosiaLibCS" Version="2018.12.6.1" />
</ItemGroup>
</Project>