Сообщение Re: .Net Core, AppDomain, RPC свой велосипед от 28.02.2017 9:38
Изменено 28.02.2017 10:19 Serginio1
Re: .Net Core, AppDomain, RPC свой велосипед
Здравствуйте, Serginio1, Вы писали:
Я прекрасно понимаю, что это никому не нужно. Но нужно доделать.
Сил вложено немало. В итоге получилось поделие даже не хуже WCF.
А по мне даже и лучше. Больше возможностей. И при этом можне не писать серверный код.
Очень близко к AppDomain, только все объекты являются MarshalByRefObject.
Поэтому прошу совета помочь оформить и покритиковать.
Что сейчас есть.
Можно подключиться к существующему серверу или запустить процесс по известному пути
После подключения можно получить типы и создавать объекты из сбороко находящиеся в папке сервера и в паках CoreClr
Поддержка статических и объектных методов, Дженерик методов с выводом типа, с дженерик аргуметами, индесаторов, итераторов
Поддержка асинхронных методов и событий. Поддержка ref и out параметров
Например
Напрямую сериализуются byte[],числа, строки,булево,Дата,char,Guid
Для AutoWrapClient передается индекс в хранилище
Но можно скопировать данные на сервер и получить ссылку
Внутри используеся Json сериализация
Но для этого нужно загрузить все используемы сборки.
Поддержка индексаторов и итераторов.
Вобщем отличие от родного кода это в вызове асинхронного метода за счет добавления слова async
Для вызова дженерик метода с дженерик аргуметами первым параметром должен идти массив типов
Ну и подключение к эвентам
Основное отличие от WCF это использование DynamicObjet. Но можно тестировать код напрямую, а затем
приспосабливать его к PPC
Я прекрасно понимаю, что это никому не нужно. Но нужно доделать.
Сил вложено немало. В итоге получилось поделие даже не хуже WCF.
А по мне даже и лучше. Больше возможностей. И при этом можне не писать серверный код.
Очень близко к AppDomain, только все объекты являются MarshalByRefObject.
Поэтому прошу совета помочь оформить и покритиковать.
Что сейчас есть.
Можно подключиться к существующему серверу или запустить процесс по известному пути
if (LoadLocalServer)
{
// connector = ClientRPC.TCPClientConnector.LoadAndConnectToLocalServer(GetParentDir(dir, 4) + $@"\Server\Server\bin\Release\netcoreapp1.1\Server.dll");
connector = ClientRPC.TCPClientConnector.LoadAndConnectToLocalServer(GetParentDir(dir, 4) + $@"\Server\Server\bin\Debug\netcoreapp1.1\Server.dll");
}
else
{
connector = new ClientRPC.TCPClientConnector("127.0.0.1", port);
// Нужен для асинхронных методов и Событий
// Если их нет то и смысла слушать порт нет
port = ClientRPC.TCPClientConnector.GetAvailablePort(6892);
connector.Open(port, 2);
}
После подключения можно получить типы и создавать объекты из сбороко находящиеся в папке сервера и в паках CoreClr
CoreClrDir = GetDirName(typeof(string));
NetObjectToNativeDir = GetDirName(typeof(AutoWrap));
Поддержка статических и объектных методов, Дженерик методов с выводом типа, с дженерик аргуметами, индесаторов, итераторов
Поддержка асинхронных методов и событий. Поддержка ref и out параметров
Например
static async Task<object> GetGenericAsyncResult(dynamic TO)
{
//public async Task<V> GenericMethodAsync<K, V>(K param, string param4 = "Test")
object resTask = await TO.async.GenericMethodAsync(new object[] { "System.Int32", "System.String" }, 44);
return resTask;
}
static void TestGenericMethods(ClientRPC.TCPClientConnector connector)
{
Dictionary<int, string> ClientDict = new Dictionary<int, string>()
{
[1] = "Один",
[2] = "Второй2",
[3] = "Один3"
};
var @Dictionary2 = wrap.GetType("System.Collections.Generic.Dictionary`2", "System.Collections");
var @DictionaryIntString = wrap.GetGenericType(@Dictionary2, "System.Int32", "System.String");
// Скопируем словарь на сервер
// Закомментированы различные варианты
// var dict = connector.CoryTo(@DictionaryIntString, ClientDict);
// var dict = connector.CoryTo("System.Collections.Generic.Dictionary`2[System.Int32, System.String]", ClientDict);
// Скопируем словарь на сервер
var dict = connector.CoryTo(ClientDict);
Console.WriteLine(wrap.toString(dict));
Console.WriteLine(dict[2]);
// Получим тип из сборки TestDll
var @TestClass = wrap.GetType("TestDllForCoreClr.TestClass", "TestDll");
// Создадим объект на сервере используя метод _new
var TO = @TestClass._new("Property from Constructor");
// Test асинхронного вызова дженерик метода
var resGM = GetGenericAsyncResult(TO).Result;
Console.WriteLine("Вызов дженерик метода с аргументами типов async " + resGM);
// Вызовем дженерик метод с автовыводом типа
// public T GenericMethod<V, T>(V param1, T param2, V param3)
resGM = TO.GenericMethod(dict, 99, "Hello");
Console.WriteLine("Вызов дженерик метода с выводом типа " + resGM);
// Test Generic Method с параметрами по умолчанию
//public string GenericMethodWithDefaulParam<K, V>(Dictionary<K, V> param1, K param2, int param3 = 4, string param4 = "Test")
var @Int32 = wrap.GetType("System.Int32");
resGM = TO.GenericMethodWithDefaulParam(dict, 99);
Console.WriteLine("Вызов дженерик метода с автовыводом типов " + resGM);
resGM = TO.GenericMethodWithDefaulParam(pp(@Int32, "System.String"), dict, 99);
Console.WriteLine("Вызов дженерик метода с аргументами типов " + resGM);
// Test Generic Method с параметрами массивом
// public string GenericMethodWithParams<K, V>(Dictionary<K, V> param1, K param2, params string[] args)
resGM = TO.GenericMethodWithParams(dict, 99, "First", "Second");
Console.WriteLine("Вызов дженерик метода с автовыводом типов " + resGM);
resGM = TO.GenericMethodWithParams(pp(@Int32, "System.String"), dict, 99, "First", "Second");
Console.WriteLine("Вызов дженерик метода с аргументами типов " + resGM);
// public V GenericMethodWithRefParam<К,V >(К param, V param2, ref string param3)
var OutParam = new ClientRPC.RefParam("TroLoLo");
resGM = TO.GenericMethodWithRefParam(5, "GenericMethodWithRefParam", OutParam);
Console.WriteLine($@"Вызов дженерик метода с автовыводом типов Ref {resGM} {OutParam.Value}");
var GenericArgs = new object[] { "System.String", "System.String" };
resGM = TO.GenericMethodWithRefParam(GenericArgs, null, "GenericMethodWithRefParam", OutParam);
Console.WriteLine($@"Вызов дженерик метода с дженерик аргументами Ref {resGM} {OutParam.Value}");
// Test return null
resGM = TO.GenericMethodWithRefParam(GenericArgs, null, null, OutParam);
Console.WriteLine($@"Вызов дженерик метода с дженерик аргументами Ref {resGM} {OutParam}");
}
Напрямую сериализуются byte[],числа, строки,булево,Дата,char,Guid
Для AutoWrapClient передается индекс в хранилище
Но можно скопировать данные на сервер и получить ссылку
var dict = connector.CoryTo(ClientDict);
Внутри используеся Json сериализация
// Сериализуем объект и отправим представление типа ввиде AssemblyQualifiedName
public dynamic CoryTo(object obj)
{
string type = obj.GetType().AssemblyQualifiedName;
var str = JsonConvert.SerializeObject(obj);
return CoryTo(type, str);
}
Но для этого нужно загрузить все используемы сборки.
static void TestSerializeObject(ClientRPC.TCPClientConnector connector)
{
var obj = new TestDllForCoreClr.TestClass("Объект на стороне Клиента");
dynamic test = null;
try
{
test = connector.CoryTo(obj);
}
catch (Exception)
{
Console.WriteLine("Ошибка " + connector.LastError);
var assembly = wrap.GetAssembly("TestDll");
test = connector.CoryTo(obj);
}
Console.WriteLine(test.ObjectProperty);
}
Поддержка индексаторов и итераторов.
string[] sa = new string[] { "Нулевой", "Первый", "Второй", "Третий", "Четвертый" };
var ServerSA = connector.ArrayCoryTo("System.String", sa);
Console.WriteLine("ServerSA[2] " + ServerSA[2]);
ServerSA[2] = "Изменен Параметр по индексу 2";
Console.WriteLine("ServerSA[2] " + ServerSA[2]);
foreach (string value in ServerSA)
Console.WriteLine("Values " + value);
var Dictionary2 = wrap.GetType("System.Collections.Generic.Dictionary`2", "System.Collections");
var DictionaryIntString = wrap.GetGenericType(Dictionary2, "System.Int32", "System.String");
//var dict = wrap.New(DictionaryIS);
Dictionary<int, string> ClientDict = new Dictionary<int, string>()
{
[1] = "Один",
[2] = "Второй2",
[3] = "Один3"
};
foreach (string value in ServerSA)
Console.WriteLine("Values " + value);
Console.WriteLine("new " + DictionaryIntString._new());
// Можно просто connector.CoryTo(ClientDict);
// Но бывает что тип только на сервере. На клиенте такого типа нет
//Но можно использоварть ExpandoObject или JObject
var dict = connector.CoryTo(DictionaryIntString, ClientDict);
Console.WriteLine("dict[2] " + dict[2]);
dict[2] = "Два";
Console.WriteLine("dict[2] " + dict[2]);
// используем класс ClientRPC.RefParam для получения измененного параметра.
var OutParam = new ClientRPC.RefParam();
if (dict.TryGetValue(2, OutParam))
{
Console.WriteLine("OutParam " + OutParam.Value);
}
Вобщем отличие от родного кода это в вызове асинхронного метода за счет добавления слова async
object resTask = await TO.async.GenericMethodAsync(new object[] { "System.Int32", "System.String" }, 44);
Для вызова дженерик метода с дженерик аргуметами первым параметром должен идти массив типов
// public V GenericMethodWithRefParam<К,V >(К param, V param2, ref string param3)
var OutParam = new ClientRPC.RefParam("TroLoLo");
var GenericArgs = new object[] { "System.String", "System.String" };
resGM = TO.GenericMethodWithRefParam(GenericArgs, null, "GenericMethodWithRefParam", OutParam);
Ну и подключение к эвентам
static public void EventWithTwoParameter(dynamic value)
{
Console.WriteLine("EventWithTwoParameter" + wrap.toString(value));
value(ClientRPC.AutoWrapClient.FlagDeleteObject);
}
// параметр value:System.String
static public void EventWithOneParameter(dynamic value)
{
Console.WriteLine("EventWithOneParameter " + wrap.toString(value));
}
static public void EventWithOutParameter(dynamic value)
{
Console.WriteLine("EventWithOutParameter" + wrap.toString(value));
}
static void RunTestEvent(ClientRPC.TCPClientConnector connector)
{
var EventTest = wrap.GetType("TestDllForCoreClr.EventTest", "TestDll");
// var test = wrap.New(EventTest);
var test = EventTest._new();
var wrapForEvents = connector.CreateWrapperForEvents(test);
wrapForEvents.AddEventHandler("EventWithTwoParameter", new Action<dynamic>(EventWithTwoParameter));
wrapForEvents.AddEventHandler("EventWithOneParameter", new Action<dynamic>(EventWithOneParameter));
wrapForEvents.AddEventHandler("EventWithOutParameter", new Action<dynamic>(EventWithOutParameter));
test.Run();
}
Основное отличие от WCF это использование DynamicObjet. Но можно тестировать код напрямую, а затем
приспосабливать его к PPC
Re: .Net Core, AppDomain, RPC свой велосипед
Здравствуйте, Serginio1, Вы писали:
Я прекрасно понимаю, что это никому не нужно. Но нужно доделать.
Сил вложено немало. В итоге получилось поделие даже не хуже WCF.
А по мне даже и лучше. Больше возможностей. И при этом можне не писать серверный код.
Очень близко к AppDomain, только все объекты являются MarshalByRefObject.
Поэтому прошу совета помочь оформить и покритиковать.
Что сейчас есть.
Можно подключиться к существующему серверу или запустить процесс по известному пути
После подключения можно получить типы и создавать объекты из сбороко находящиеся в папке сервера и в паках CoreClr
Поддержка статических и объектных методов, Дженерик методов с выводом типа, с дженерик аргуметами, индесаторов, итераторов
Поддержка асинхронных методов и событий. Поддержка ref и out параметров
Например
Напрямую сериализуются byte[],числа, строки,булево,Дата,char,Guid
Для AutoWrapClient передается индекс в хранилище
Но можно скопировать данные на сервер и получить ссылку
Внутри используеся Json сериализация
При этом мы можем получить и ссылку на byte[], так при обычном методе он сериализуется.
Но для этого нужно загрузить все используемы сборки.
Поддержка индексаторов и итераторов.
Вобщем отличие от родного кода это в вызове асинхронного метода за счет добавления слова async
Для вызова дженерик метода с дженерик аргуметами первым параметром должен идти массив типов
Ну и подключение к эвентам
Основное отличие от WCF это использование DynamicObjet. Но можно тестировать код напрямую, а затем
приспосабливать его к PPC
Я прекрасно понимаю, что это никому не нужно. Но нужно доделать.
Сил вложено немало. В итоге получилось поделие даже не хуже WCF.
А по мне даже и лучше. Больше возможностей. И при этом можне не писать серверный код.
Очень близко к AppDomain, только все объекты являются MarshalByRefObject.
Поэтому прошу совета помочь оформить и покритиковать.
Что сейчас есть.
Можно подключиться к существующему серверу или запустить процесс по известному пути
if (LoadLocalServer)
{
// connector = ClientRPC.TCPClientConnector.LoadAndConnectToLocalServer(GetParentDir(dir, 4) + $@"\Server\Server\bin\Release\netcoreapp1.1\Server.dll");
connector = ClientRPC.TCPClientConnector.LoadAndConnectToLocalServer(GetParentDir(dir, 4) + $@"\Server\Server\bin\Debug\netcoreapp1.1\Server.dll");
}
else
{
connector = new ClientRPC.TCPClientConnector("127.0.0.1", port);
// Нужен для асинхронных методов и Событий
// Если их нет то и смысла слушать порт нет
port = ClientRPC.TCPClientConnector.GetAvailablePort(6892);
connector.Open(port, 2);
}
После подключения можно получить типы и создавать объекты из сбороко находящиеся в папке сервера и в паках CoreClr
CoreClrDir = GetDirName(typeof(string));
NetObjectToNativeDir = GetDirName(typeof(AutoWrap));
Поддержка статических и объектных методов, Дженерик методов с выводом типа, с дженерик аргуметами, индесаторов, итераторов
Поддержка асинхронных методов и событий. Поддержка ref и out параметров
Например
static async Task<object> GetGenericAsyncResult(dynamic TO)
{
//public async Task<V> GenericMethodAsync<K, V>(K param, string param4 = "Test")
object resTask = await TO.async.GenericMethodAsync(new object[] { "System.Int32", "System.String" }, 44);
return resTask;
}
static void TestGenericMethods(ClientRPC.TCPClientConnector connector)
{
Dictionary<int, string> ClientDict = new Dictionary<int, string>()
{
[1] = "Один",
[2] = "Второй2",
[3] = "Один3"
};
var @Dictionary2 = wrap.GetType("System.Collections.Generic.Dictionary`2", "System.Collections");
var @DictionaryIntString = wrap.GetGenericType(@Dictionary2, "System.Int32", "System.String");
// Скопируем словарь на сервер
// Закомментированы различные варианты
// var dict = connector.CoryTo(@DictionaryIntString, ClientDict);
// var dict = connector.CoryTo("System.Collections.Generic.Dictionary`2[System.Int32, System.String]", ClientDict);
// Скопируем словарь на сервер
var dict = connector.CoryTo(ClientDict);
Console.WriteLine(wrap.toString(dict));
Console.WriteLine(dict[2]);
// Получим тип из сборки TestDll
var @TestClass = wrap.GetType("TestDllForCoreClr.TestClass", "TestDll");
// Создадим объект на сервере используя метод _new
var TO = @TestClass._new("Property from Constructor");
// Test асинхронного вызова дженерик метода
var resGM = GetGenericAsyncResult(TO).Result;
Console.WriteLine("Вызов дженерик метода с аргументами типов async " + resGM);
// Вызовем дженерик метод с автовыводом типа
// public T GenericMethod<V, T>(V param1, T param2, V param3)
resGM = TO.GenericMethod(dict, 99, "Hello");
Console.WriteLine("Вызов дженерик метода с выводом типа " + resGM);
// Test Generic Method с параметрами по умолчанию
//public string GenericMethodWithDefaulParam<K, V>(Dictionary<K, V> param1, K param2, int param3 = 4, string param4 = "Test")
var @Int32 = wrap.GetType("System.Int32");
resGM = TO.GenericMethodWithDefaulParam(dict, 99);
Console.WriteLine("Вызов дженерик метода с автовыводом типов " + resGM);
resGM = TO.GenericMethodWithDefaulParam(pp(@Int32, "System.String"), dict, 99);
Console.WriteLine("Вызов дженерик метода с аргументами типов " + resGM);
// Test Generic Method с параметрами массивом
// public string GenericMethodWithParams<K, V>(Dictionary<K, V> param1, K param2, params string[] args)
resGM = TO.GenericMethodWithParams(dict, 99, "First", "Second");
Console.WriteLine("Вызов дженерик метода с автовыводом типов " + resGM);
resGM = TO.GenericMethodWithParams(pp(@Int32, "System.String"), dict, 99, "First", "Second");
Console.WriteLine("Вызов дженерик метода с аргументами типов " + resGM);
// public V GenericMethodWithRefParam<К,V >(К param, V param2, ref string param3)
var OutParam = new ClientRPC.RefParam("TroLoLo");
resGM = TO.GenericMethodWithRefParam(5, "GenericMethodWithRefParam", OutParam);
Console.WriteLine($@"Вызов дженерик метода с автовыводом типов Ref {resGM} {OutParam.Value}");
var GenericArgs = new object[] { "System.String", "System.String" };
resGM = TO.GenericMethodWithRefParam(GenericArgs, null, "GenericMethodWithRefParam", OutParam);
Console.WriteLine($@"Вызов дженерик метода с дженерик аргументами Ref {resGM} {OutParam.Value}");
// Test return null
resGM = TO.GenericMethodWithRefParam(GenericArgs, null, null, OutParam);
Console.WriteLine($@"Вызов дженерик метода с дженерик аргументами Ref {resGM} {OutParam}");
}
Напрямую сериализуются byte[],числа, строки,булево,Дата,char,Guid
Для AutoWrapClient передается индекс в хранилище
Но можно скопировать данные на сервер и получить ссылку
var dict = connector.CoryTo(ClientDict);
Внутри используеся Json сериализация
// Сериализуем объект и отправим представление типа ввиде AssemblyQualifiedName
public dynamic CoryTo(object obj)
{
string type = obj.GetType().AssemblyQualifiedName;
var str = JsonConvert.SerializeObject(obj);
return CoryTo(type, str);
}
При этом мы можем получить и ссылку на byte[], так при обычном методе он сериализуется.
Но для этого нужно загрузить все используемы сборки.
static void TestSerializeObject(ClientRPC.TCPClientConnector connector)
{
// Получим на клиенте объект и скопируем его на сервер
var obj = new TestDllForCoreClr.TestClass("Объект на стороне Клиента");
dynamic test = null;
try
{
test = connector.CoryTo(obj);
}
catch (Exception)
{
Console.WriteLine("Ошибка " + connector.LastError);
var assembly = wrap.GetAssembly("TestDll");
test = connector.CoryTo(obj);
}
Console.WriteLine(test.ObjectProperty);
}
Поддержка индексаторов и итераторов.
string[] sa = new string[] { "Нулевой", "Первый", "Второй", "Третий", "Четвертый" };
var ServerSA = connector.ArrayCoryTo("System.String", sa);
Console.WriteLine("ServerSA[2] " + ServerSA[2]);
ServerSA[2] = "Изменен Параметр по индексу 2";
Console.WriteLine("ServerSA[2] " + ServerSA[2]);
foreach (string value in ServerSA)
Console.WriteLine("Values " + value);
var Dictionary2 = wrap.GetType("System.Collections.Generic.Dictionary`2", "System.Collections");
var DictionaryIntString = wrap.GetGenericType(Dictionary2, "System.Int32", "System.String");
//var dict = wrap.New(DictionaryIS);
Dictionary<int, string> ClientDict = new Dictionary<int, string>()
{
[1] = "Один",
[2] = "Второй2",
[3] = "Один3"
};
foreach (string value in ServerSA)
Console.WriteLine("Values " + value);
Console.WriteLine("new " + DictionaryIntString._new());
// Можно просто connector.CoryTo(ClientDict);
// Но бывает что тип только на сервере. На клиенте такого типа нет
//Но можно использоварть ExpandoObject или JObject
var dict = connector.CoryTo(DictionaryIntString, ClientDict);
Console.WriteLine("dict[2] " + dict[2]);
dict[2] = "Два";
Console.WriteLine("dict[2] " + dict[2]);
// используем класс ClientRPC.RefParam для получения измененного параметра.
var OutParam = new ClientRPC.RefParam();
if (dict.TryGetValue(2, OutParam))
{
Console.WriteLine("OutParam " + OutParam.Value);
}
Вобщем отличие от родного кода это в вызове асинхронного метода за счет добавления слова async
object resTask = await TO.async.GenericMethodAsync(new object[] { "System.Int32", "System.String" }, 44);
Для вызова дженерик метода с дженерик аргуметами первым параметром должен идти массив типов
// public V GenericMethodWithRefParam<К,V >(К param, V param2, ref string param3)
var OutParam = new ClientRPC.RefParam("TroLoLo");
var GenericArgs = new object[] { "System.String", "System.String" };
resGM = TO.GenericMethodWithRefParam(GenericArgs, null, "GenericMethodWithRefParam", OutParam);
Ну и подключение к эвентам
static public void EventWithTwoParameter(dynamic value)
{
Console.WriteLine("EventWithTwoParameter" + wrap.toString(value));
value(ClientRPC.AutoWrapClient.FlagDeleteObject);
}
// параметр value:System.String
static public void EventWithOneParameter(dynamic value)
{
Console.WriteLine("EventWithOneParameter " + wrap.toString(value));
}
static public void EventWithOutParameter(dynamic value)
{
Console.WriteLine("EventWithOutParameter" + wrap.toString(value));
}
static void RunTestEvent(ClientRPC.TCPClientConnector connector)
{
var EventTest = wrap.GetType("TestDllForCoreClr.EventTest", "TestDll");
// var test = wrap.New(EventTest);
var test = EventTest._new();
var wrapForEvents = connector.CreateWrapperForEvents(test);
wrapForEvents.AddEventHandler("EventWithTwoParameter", new Action<dynamic>(EventWithTwoParameter));
wrapForEvents.AddEventHandler("EventWithOneParameter", new Action<dynamic>(EventWithOneParameter));
wrapForEvents.AddEventHandler("EventWithOutParameter", new Action<dynamic>(EventWithOutParameter));
test.Run();
}
Основное отличие от WCF это использование DynamicObjet. Но можно тестировать код напрямую, а затем
приспосабливать его к PPC