|
Вопрос по NetObjectToIDispatch | ☑ | ||
---|---|---|---|---|
0
oleg_km
09.05.13
✎
21:51
|
Попробовал v8: Объекты Net в IDispatch вроде все нормально.
Попробовал: ТипПорт = объект.GetTypeByStr("System.IO.Ports.SerialPort"); Здесь ругается: Can't resolve type Активатор = объект.Activator; обПорт = Активатор.CreateInstance(ТипПорт); обПорт.PortName = "COM43"; обПорт.BaudRate = 115200; обПорт.ReadTimeout = 500; обПорт.Open(); обПорт.Write("AT" + Символы.ВК); Сообщить(обПорт.ReadExisting()); обПорт.Close(); Ругается: |
|||
1
oleg_km
09.05.13
✎
22:08
|
Точнее:
Произошла исключительная ситуация (mscorlib): Could not resolve type 'System.IO.Ports.SerialPort'. |
|||
2
Jaap Vduul
09.05.13
✎
23:23
|
дотнет фрэймворк, наверное, старенький...
|
|||
3
oleg_km
10.05.13
✎
09:05
|
Стоит 4, но я так понимаю при запуске подхватилась двойка или как это происходит?
|
|||
4
oleg_km
10.05.13
✎
09:53
|
Спасибо за наводку, вот так заработало:
ТипПорт = объект.GetTypeByStr("System.IO.Ports.SerialPort, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", ""); |
|||
5
oleg_km
10.05.13
✎
13:09
|
Теперь возник вопрос с конструктором с параметрами и по поводу использования перечислений:
ТипСокет = объект.GetTypeByStr("System.Net.Sockets.Socket, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", ""); ТипАдрес = объект.GetTypeByStr("System.Net.Sockets.AddressFamily, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", ""); ТипТип = объект.GetTypeByStr("System.Net.Sockets.SocketType, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", ""); ТипПротокол = объект.GetTypeByStr("System.Net.Sockets.ProtocolType, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", ""); //мсИсх = Новый Массив; //мсИсх.Добавить(ТипАдрес.InterNetwork); //мсИсх.Добавить(ТипТип.Stream); //мсИсх.Добавить(ТипПротокол.Tcp); //мс = Новый COMSafeArray(мсИсх, "VT_VARIANT"); //обСокет = Активатор.CreateInstance(ТипСокет, ТипАдрес.InterNetwork, ТипТип.Stream, ТипПротокол.Tcp); обСокет = Активатор.CreateInstance(ТипСокет, 2, 1, 6); На ТипАдрес.InterNetwork ругается метод не найден, хотя в отладчике виден, в CreateInstance не понятно как передать массив параметров |
|||
6
oleg_km
10.05.13
✎
14:09
|
Вот вроде должен быть правильный вариант:
ТипСокет = объект.GetTypeByStr("System.Net.Sockets.Socket, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", ""); ТипАдрес = объект.GetTypeByStr("System.Net.Sockets.AddressFamily, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", ""); ТипТип = объект.GetTypeByStr("System.Net.Sockets.SocketType, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", ""); ТипПротокол = объект.GetTypeByStr("System.Net.Sockets.ProtocolType, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", ""); мсПарам = объект.CreateArray("System.Object", 3); мсПарам.SetValue(ТипАдрес.InterNetwork, 0); мсПарам.SetValue(ТипТип.Stream, 1); мсПарам.SetValue(ТипПротокол.Tcp, 2); обСокет = Активатор.CreateInstance(ТипСокет, мсПарам); Но на ТипАдрес.InterNetwork ругается. Автор, подскажи, что не так? |
|||
7
Serginio1
10.05.13
✎
14:55
|
Ты сначала на шарпе оттести, затем в 1С перенеси. А эта библиотека просто Оле обертка нетовских объектов. Там есть сложности с некоторыми типами но они решаемы
http://rsdn.ru/forum/dotnet/4320177 Вот последний рабочий вариант http://rsdn.ru/forum/dotnet/4719475 |
|||
8
oleg_km
10.05.13
✎
15:08
|
(7) На шарпе все работает. Проблема судя по всему, что неправильно создается обертка для перечислений (enum), т.к. я сделал тестовый пример, где нужный енум возвращается из шарпа и все заработало:
public object Get1() { return new AutoWrap(AddressFamily.InterNetwork); } public object Get2() { return new AutoWrap(SocketType.Stream); } public object Get3() { return new AutoWrap(ProtocolType.Tcp); } мсПарам.SetValue(объект.Get1(), 0); мсПарам.SetValue(объект.Get2(), 1); мсПарам.SetValue(объект.Get3(), 2); Можешь подсказать что добавить в товй компонент, чтобы он правильно обрабатыал перечисления? |
|||
9
Serginio1
10.05.13
✎
15:08
|
А вообще у InterNetwork значение 2
то есть должно быть мсПарам.SetValue(ТипАдрес, 2); |
|||
10
Serginio1
10.05.13
✎
15:10
|
Вернее Активатор.CreateInstance(ТипАдрес, мсПарам);
|
|||
11
Serginio1
10.05.13
✎
15:12
|
(10) не совсем верно это получение значения. Должно работать мсПарам.SetValue(ТипАдрес, 2); так как в рефлекторе InterNetwork = 2
|
|||
12
oleg_km
10.05.13
✎
15:12
|
то есть должно быть мсПарам.SetValue(ТипАдрес, 2);
Нет 2 - это же индекс в массиве, еще раз, вот ключевая часть кода: мсПарам = объект.CreateArray("System.Object", 3); мсПарам.SetValue(ТипАдрес.InterNetwork, 0); мсПарам.SetValue(ТипТип.Stream, 1); мсПарам.SetValue(ТипПротокол.Tcp, 2); обСокет = Активатор.CreateInstance(ТипСокет, мсПарам); Типы все получены, но получить конкретное перечисление не получается. Я пытался подсунуть массив целых с указанием значений перечислений, но дот нет заругался, что нет такого конструктора (с целыми параметрами), что логично, т.к. шарп не делает неявного приведения. |
|||
13
Serginio1
10.05.13
✎
15:13
|
надо будет перечисления посмотретьДа понял Попробуй так
Активатор.CreateInstance(ТипАдрес, мсПарам); мсПарам.SetValue(Активатор.CreateInstance(ТипАдрес, мсПарам), 0); |
|||
14
Serginio1
10.05.13
✎
15:14
|
Тьфу мсПарам.SetValue(Активатор.CreateInstance(ТипАдрес, 2), 0);
|
|||
15
Serginio1
10.05.13
✎
15:19
|
Или object obj1 = Enum.ToObject(ТипАдрес, "InterNetwork");
|
|||
16
oleg_km
10.05.13
✎
15:23
|
(14) Сказал нет такого конструктора
(15) А этоя вообще не понял как перевести на 1С. Enum это чей член? |
|||
17
Serginio1
10.05.13
✎
15:27
|
То есть Активатор.CreateInstance(ТипАдрес, 2) для энума не идет?
объект.GetTypeByStr("System.Enum") |
|||
18
Serginio1
10.05.13
✎
15:31
|
Или сделай метод public object ПолучитьПеречисление(Тип,Предствление)
{ return new AutoWrap(Enum.ToObject(Тип,Представление); } |
|||
19
Serginio1
10.05.13
✎
15:36
|
Я в новой версии добавил два метода
public object CreateObject(string type) { return new AutoWrap(System.Activator.CreateInstance(Type.GetType(type))); } public object CreateObjectWhithParam(string type,Object[] args) { return new AutoWrap(System.Activator.CreateInstance(Type.GetType(type), args)); } |
|||
20
Serginio1
10.05.13
✎
15:42
|
А вообще то Энум это чтсло и должно проходить как
сПарам.SetValue(2, 0); |
|||
21
oleg_km
10.05.13
✎
15:47
|
(21) Я же писал: так не катит, он потом говорит, не конструктора с типом целый. Ну и в букваре написано, что неявные преобразования целых в перечисления не производятся. Можно наверное попробовать сделать функцию аналог as. типа на входе тип и исходное значение, на выходе объект перечисления. Но я хочу сделать все-таки через имя. Сейчас кухню допылесосю и попробую
|
|||
22
Serginio1
10.05.13
✎
15:56
|
21 Тогда сделай 18.
В 20 там установка сПарам.SetValue(2, 0); Установить значение то он даст а вот на вызове обСокет = Активатор.CreateInstance(ТипСокет, мсПарам); саоткнется |
|||
23
Serginio1
10.05.13
✎
16:01
|
Кстати Enum.ToObject подходит и для чисел http://msdn.microsoft.com/en-us/library/e3c9ct1y.aspx
|
|||
24
oleg_km
10.05.13
✎
16:11
|
(18)
public object ПолучитьПеречисление(Тип,Предствление) { return new AutoWrap(Enum.ToObject(Тип,Представление); } я сделал: public object ПолучитьПеречисление(Тип, string Предствление) { return new AutoWrap(Enum.Parse(Тип, Представление); } а вот какой тип должен иметь Тип. Если Type, то падает в момент вызова неизвестная ошибка, если объект, то падает при приведении |
|||
25
oleg_km
10.05.13
✎
16:19
|
Все, получилось. Я примерно понял в каком направлении рыть. Съезжу яхту покрашу и вечером попробую сделать финальный вариант.
|
|||
26
Serginio1
10.05.13
✎
16:28
|
http://msdn.microsoft.com/en-us/library/dd783499.aspx
не совсем подходит. Там дженерики. По ним отдельная рефлексия public static bool TryParse<TEnum>( string value, out TEnum result ) where TEnum : struct А 18 не проходит? По идее должен походить для предствления ввиде интов и строк. http://stackoverflow.com/questions/29482/cast-int-to-enum-in-c-sharp |
|||
27
Serginio1
10.05.13
✎
16:44
|
Немного не в тему у Enum есть метод
public static object Parse(Type enumType, string value) { return Parse(enumType, value, false); } вообще то должен быть Type. Посмотри новый вариант там есть public object ТипКакОбъект(object Тип) { Type T=((Type)Тип); return new AutoWrap(T, T.GetType()); } |
|||
28
Serginio1
10.05.13
✎
16:53
|
Непомню зачем тестил объект=Новый COMОбъект("NetObjectToIDispatch");
Массив=объект.CreateArray("System.String",100); для сч=0 по 99 Цикл Массив.SetValue(Строка(сч),сч); КонецЦикла; Для каждого стр из Массив Цикл Сообщить(стр); КонецЦикла; ЛистТип=объект.ПолучитьТип("System.Collections.Generic.List`1[System.String]",""); //ЛистТип=объект.ПолучитьТип("System.Collections.ArrayList",""); Лист=объект.Activator.CreateInstance(ЛистТип); // Массив=Лист.ToArray(); Массив=объект.ВыполнитьМетод(Лист,"ToArray"); Тип=объект.ТипКакОбъект(ЛистТип); Методы=Тип.GetMethods(); Методы=объект.ПолучитьМетоды(ЛистТип); Для каждого стр из Методы Цикл Сообщить(Стр.Name); КонецЦикла; Для сч=1 по 100 Цикл Лист.Add(""+Сч); КонецЦикла; Сообщить(Лист.Count); Стр=Лист.ToString(); Сообщить(Стр); //Массив=объект.ПолучитьМассивИзЛистаСтрок(Лист); // Для каждого стр из массив Цикл // Сообщить(Стр); //КонецЦикла; // Массив=Лист.ToArray(); Массив=объект.ВыполнитьМетод(Лист,"ToArray"); Тип=Лист.GetType(); // Массив=Лист.ToArray(объект.ПолучитьТип("System.String","")); Сообщить(Массив.ToString()); Для каждого стр из массив Цикл Сообщить(Стр); КонецЦикла; |
|||
29
Serginio1
10.05.13
✎
16:56
|
public object ПолучитьМетоды(object Тип)
{ // AutoWrap T = ((AutoWrap)Тип); // return T.T.GetMethods(); return new AutoWrap(((Type)Тип).GetMethods()); } То есть в public object ПолучитьПеречисление(object Тип,string Предствление) { return new AutoWrap(Enum.ToObject((Type) Тип,Представление); } |
|||
30
Serginio1
10.05.13
✎
18:18
|
То есть нужно тип постоянно приводить. Вот такая засада.
|
|||
31
Serginio1
10.05.13
✎
18:30
|
Либо в ОбернутьОбъект(object obj) добавить
if (obj is Type) obj = new AutoWrap((Type)obj); |
|||
32
Serginio1
10.05.13
✎
18:38
|
Тьфу прошу прощения в новой версии уже есть
if (ЭтоТип) obj = T.InvokeMember(name, invokeAttr, binder, null, args, modifiers, culture, namedParameters); else obj = T.InvokeMember(name, invokeAttr, binder, O, args, modifiers, culture, namedParameters); А вот для передаваемого параметра нужно добавить проверку на тип if (args != null && args.Length > 0) { for (int x = 0; x < args.Length; x++) { if (args[x] is AutoWrap) if (args[x].ЭтоТип) {args[x] = (Type)((AutoWrap)args[x]).O;} else { args[x] = ((AutoWrap)args[x]).O; } } } или {args[x] = (Type)((AutoWrap)args[x]).T;} |
|||
33
zladenuw
10.05.13
✎
19:17
|
и что с этого будет в итоге ? своя обвертка для 1с или че ?
|
|||
34
oleg_km
10.05.13
✎
19:55
|
В общем сделал вот так:
public object InvokeMember(string name, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, object target, object[] args, System.Reflection.ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, string[] namedParameters) ... object obj; if (T.IsEnum) obj = Enum.Parse(T, name); else { if (isType) obj = T.InvokeMember(name, invokeAttr, binder, null, args, modifiers, culture, namedParameters); else obj = T.InvokeMember(name, invokeAttr, binder, O, args, modifiers, culture, namedParameters); } Т.е. нужное мне вариант перечисления парсится. Вызов как шарпе: ТипАдрес = объект.GetTypeByStr("System.Net.Sockets.AddressFamily, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", ""); Сообщить(ТипАдрес.InterNetwork.ToString()); Только у перечисления так же есть методы, которые нужно пропустить в Invoke. Подскажи, как invokeAttr протестировать на наличие флага InvokeMethod, элементарщину пропустил на сях? |
|||
35
oleg_km
10.05.13
✎
20:04
|
Вот так пока сделал условие:
if (T.IsEnum && !invokeAttr.HasFlag(BindingFlags.InvokeMethod)) |
|||
36
oleg_km
10.05.13
✎
20:28
|
Ура, работает:
объект = Новый COMОбъект("NetObjectToIDispatch"); Активатор = объект.Activator; Если Ложь Тогда //Типмд5 = объект.GetTypeByStr("System.Security.Cryptography.MD5CryptoServiceProvider", ""); //мд5 = Активатор.CreateInstance(Типмд5); мд5 = объект.CreateObject("System.Security.Cryptography.MD5CryptoServiceProvider"); типЭнкодинг = объект.GetTypeByStr("System.Text.Encoding",""); мсДанные = типЭнкодинг.Default.GetBytes("Строка"); рез = мд5.ComputeHash(мсДанные); // Сообщить(типЭнкодинг.Default.GetString(рез)); Для ии = 0 По рез.Length - 1 Цикл Сообщить(рез.GetValue(ии)); КонецЦикла; КонецЕсли; Если Ложь Тогда ТипПорт = объект.GetTypeByStr("System.IO.Ports.SerialPort, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", ""); обПорт = Активатор.CreateInstance(ТипПорт); обПорт.PortName = "COM43"; обПорт.BaudRate = 115200; обПорт.ReadTimeout = 500; обПорт.Open(); обПорт.Write("AT" + Символы.ВК); Слееп = объект.GetTypeByStr("System.Threading.Thread", ""); Слееп.Sleep(1000); Сообщить(обПорт.ReadExisting()); обПорт.Close(); КонецЕсли; Если Истина Тогда ТипСокет = объект.GetTypeByStr("System.Net.Sockets.Socket, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", ""); ТипАдрес = объект.GetTypeByStr("System.Net.Sockets.AddressFamily, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", ""); ТипТип = объект.GetTypeByStr("System.Net.Sockets.SocketType, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", ""); ТипПротокол = объект.GetTypeByStr("System.Net.Sockets.ProtocolType, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", ""); мсПарам = объект.CreateArray("System.Object", 3); мсПарам.SetValue(ТипАдрес.InterNetwork, 0); мсПарам.SetValue(ТипТип.Stream, 1); мсПарам.SetValue(ТипПротокол.Tcp, 2); обСокет = Активатор.CreateInstance(ТипСокет, мсПарам); обСокет.Connect("smtp.mail.ru", 25); Слееп = объект.GetTypeByStr("System.Threading.Thread", ""); Слееп.Sleep(200); мсРез = объект.CreateArray("System.Byte", обСокет.Available); обСокет.Receive(мсРез); типЭнкодинг = объект.GetTypeByStr("System.Text.Encoding",""); Сообщить("1: " + типЭнкодинг.Default.GetString(мсРез)); мсДанные = типЭнкодинг.Default.GetBytes("QUIT" + Символы.ВК + Символы.ПС); обСокет.Send(мсДанные); Слееп = объект.GetTypeByStr("System.Threading.Thread", ""); Слееп.Sleep(200); мсРез = объект.CreateArray("System.Byte", обСокет.Available); обСокет.Receive(мсРез); типЭнкодинг = объект.GetTypeByStr("System.Text.Encoding",""); Сообщить("2: " + типЭнкодинг.Default.GetString(мсРез)); ТипЗакрытие = объект.GetTypeByStr("System.Net.Sockets.SocketShutdown, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", ""); обСокет.ShutDown(ТипЗакрытие.Both); обСокет.Close(); КонецЕсли; |
|||
37
Serginio1
10.05.13
✎
21:48
|
Отлично. Но надо еще добить Type в параметрах. см 32
|
|||
38
oleg_km
10.05.13
✎
22:29
|
(37) А это для каких случаев нужно? Надышался бензина и краски и что-то голова уже не соображает
|
|||
39
Serginio1
10.05.13
✎
23:39
|
38 А то что у тебя в 24 не получалось.
|
|||
40
Serginio1
10.05.13
✎
23:47
|
39 + То что в 32 для парпметров
if (args[x].ЭтоТип) args[x] = ((AutoWrap)args[x]).T |
|||
41
oleg_km
11.05.13
✎
08:24
|
(40) Да понял, добавлю. Это для случая, если мою ссылку на тип нужно будет передать параметром в метод? Так ведь без разницы что передавать, что O что T. Для типа O == T включая тип
|
|||
42
Serginio1
11.05.13
✎
10:28
|
По идее да. Я просто не понял, что у тебя в 24 не получилось.
Просто помню с типом боролся, а что и почему уже не помню. По идее public object ПолучитьПеречисление(Type Тип, string Предствление) { return new AutoWrap(Enum.Parse(Тип, Представление); } должен проходить |
|||
43
oleg_km
11.05.13
✎
11:37
|
(42)
public object ПолучитьПеречисление(Type Тип, string Предствление) { return new AutoWrap(Enum.Parse(Тип, Представление); } должен проходить Это лишнее, лучше как в (34) дополнить public object InvokeMember, чтобы он как шарпе давал выбирать перечисление через точку У меня теперь другая проблема, под 4.0 работает, а хотелось бы под 3.5. Но там ругается не могу загрузить сборку. Позже поразбираюсь - напишу подробности. |
|||
44
Serginio1
11.05.13
✎
11:52
|
Я не про перечисления. Почему у тебя в 24
а вот какой тип должен иметь Тип. Если Type, то падает в момент вызова неизвестная ошибка, если объект, то падает при приведении А вот для 3.5 нужно и компилировать под 3.5 и соответственно в версию другую указывать не 4.0.0.0 ТипСокет = объект.GetTypeByStr("System.Net.Sockets.Socket, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", ""); |
|||
45
oleg_km
11.05.13
✎
13:17
|
Я наоборот класс NetObjectToIDispatch максимально разгрузил, оставил только
public object GetTypeByStr(string type) { return new AutoWrap(Type.GetType(type, true)); } из него можно все получить и активатор и конструктор массивов: объект = Новый COMОбъект("1CAddInNET.NET2COM"); Активатор = объект.GetTypeByStr("System.Activator"); ТипСборки = объект.GetTypeByStr("System.Reflection.Assembly"); Сборка = ТипСборки.Load("System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); ТипОбъект = объект.GetTypeByStr("System.Object"); ТипМассив = объект.GetTypeByStr("System.Array"); мсПарам = ТипМассив.CreateInstance(ТипОбъект, 3); мсПарам.SetValue(ТипАдрес.InterNetwork, 0); мсПарам.SetValue(ТипТип.Stream, 1); мсПарам.SetValue(ТипПротокол.Tcp, 2); обСокет = Активатор.CreateInstance(ТипСокет, мсПарам); обСокет.Connect("smtp.mail.ru", 25); |
|||
46
Serginio1
11.05.13
✎
13:37
|
Да я непомню уже для чего добавлял методы. Но например
public object ВыполнитьМетод(object obj,string ИмяМетода) { if (obj is AutoWrap) obj=((AutoWrap)obj).O; Type T=obj.GetType(); return new AutoWrap(T.InvokeMember(ИмяМетода,BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod, null, obj, null)); } } Специально добавил так как не выполнялся метод ToArray для дженериковского листа не проходил Активатором проще изначальнопользоваться. Масиивом тоже. http://rsdn.ru/forum/dotnet/4320177 public object ПолучитьИнтерфейс(object obj, string InterfaseName) { if (obj is AutoWrap) obj=((AutoWrap)obj).O; Type type = obj.GetType().GetInterface(InterfaseName, true); return new AutoWrap(obj, type); } |
|||
47
Serginio1
11.05.13
✎
13:38
|
И соответственно 3 конструктора
public AutoWrap() { } public AutoWrap(object obj) { O = obj; if (O is Type) { T = O as Type; ЭтоТип = true; } else { T = O.GetType(); ЭтоТип = false; } } public AutoWrap(object obj, Type type) { O = obj; T = type; ЭтоТип = false; } |
|||
48
oleg_km
11.05.13
✎
14:15
|
Ладно, нужно пробовать. Чуствую, что для полного счастья делегаты еще нужны.
|
|||
49
Serginio1
11.05.13
✎
14:19
|
(48) Нужно смотреть в сторону DynamicAssembly и генерации кода
например http://www.rsdn.ru/forum/src/3165397.1 |
|||
50
Serginio1
11.05.13
✎
14:25
|
Или посмотреть CodeDOM
http://msdn.microsoft.com/ru-ru/library/ms404245.aspx |
|||
51
oleg_km
11.05.13
✎
14:36
|
(49)(50) Мда, это по-любому будет означать четверку. В принципе невелика печаль.
|
|||
52
Serginio1
11.05.13
✎
14:40
|
(48) Вообще я эту обертку испольую для простого использования готовых классов. Например для доступа к Вэб сервисам, в тех случаях когда 1С их не понимает. Отдельно описывать все методы через Оле оберку нет смысла когда методов под сотню. И для этих случаев обертка через IReflect самое то. Для использования более специальных обработок проще использовать уже COM классы. Например Внешняя компонента .NET
|
|||
53
Serginio1
11.05.13
✎
14:46
|
Кстати а DR я использую через http://1c.proclub.ru/modules/mydownloads/personal.php?cid=115&lid=2019
Просто пишу COM объект добавляю метод void InitFrom1C(object Object1C); И все public void InitFrom1C(object Object1C) { // MessageBox.Show("InitFrom1C"); try { Event = new AutoResetEvent(false); EventTo1C = Object1C as IAsyncEvent; SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext()); Sc = SynchronizationContext.Current; } catch (Exception e) { MessageBox.Show(e.ToString()); throw e; } } |
|||
54
oleg_km
11.05.13
✎
15:44
|
(52) Да я вот тоже, начал писать обертку, вернее у меня есть на С++. Решил переделать на шарп и не хочется все писать на шарпе. Я думаю, где нужны будут события, буду делать спец. обертки, где просто синхронные функции - пользовать универсальную обертку
|
|||
55
Serginio1
11.05.13
✎
20:07
|
Вообще IReflect нужный инструмент. И его легко использовать. Только почему то не очень используемый. Хотя рыбу я взял у писателей сайтов.
Кстати нечто аналогичное на уровне динамиков можно делать и для Net через IDynamicObject http://intellitect.com/dynamically-typed-objects-with-c-4-0/ |
|||
56
Serginio1
21.05.13
✎
11:48
|
(48) Блин сам забыл
System.Delegate.CreateDelegate http://msdn.microsoft.com/en-us/library/system.delegate.createdelegate.aspx |
|||
57
Serginio1
21.05.13
✎
11:52
|
А тип делегата можно получить так http://www.rsdn.ru/forum/dotnet/5174968.1
|
|||
58
oleg_km
21.05.13
✎
12:24
|
(56)(57) Если бы еще понять как это приспособить. У меня задача такая. С помощью вышеупомянутой обертки например сделал работу с сокетом и ком-портов в синхронном режиме. Но мне кроме того нужно ее и в асинхронном, вернее нужно чтобы в 1С поступали события по аналогии с активИкс. Если можешь накидать простенький пример, как допустим классу SelialPort назначить событие DataReceived, не обязательно работающий пример, можно просто набросок? Не владею глубоко дотНетом, чтобы разобраться
|
|||
59
Serginio1
21.05.13
✎
12:49
|
Тебе нужно ВК писать например
public void InitFrom1C(object Object1C) { try { Event = new AutoResetEvent(false); EventTo1C = Object1C as IAsyncEvent; SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext()); Sc = SynchronizationContext.Current; } catch (Exception e) { MessageBox.Show(e.ToString()); throw e; } } public void ОткрытьАйПиПорт() { // Trace.WriteLine(DateTime.Now.ToString() + " - InitFrom1C " + ИдПотока.ToString()); // Trace.Flush(); ОткрытьАйПиПортСНомеромПорта(6891); } public void ОткрытьАйПиПортСНомеромПорта(int НомерПорта) { Server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPEndPoint ipEndpoint = new IPEndPoint(IPAddress.Any, НомерПорта); Server.Bind(ipEndpoint); Server.Listen(1); Server.BeginAccept(new AsyncCallback(ОбработкаСоединения), Server); } Где private void ОбработкаСоединения(IAsyncResult AsyncCall) { Socket listener = (Socket)AsyncCall.AsyncState; if (listener == null || (ЭтоЗакрытие)) return; Socket client = listener.EndAccept(AsyncCall); ВыполнитьКоманду(client); // После того как завершили соединение, говорим ОС что мы готовы принять новое listener.BeginAccept(new AsyncCallback(ОбработкаСоединения), listener); } private void ВыполнитьКоманду(Socket client) { NetworkStream стрим=new NetworkStream(client); bool ЕстьОтвет; try { ДляОбменаПоТСП.ПринятьКоманду(стрим, out команда, out данныеДляКоманды, out ЕстьОтвет); Event.Reset(); Sc.Send(d => ExternalEvent1С(), null); if (ЕстьОтвет) { Event.WaitOne(); ДляОбменаПоТСП.WriteCompressedString(стрим, Otvet); } } catch (Exception e) { ЗаписатьОшибку(DateTime.Now.ToString() + e.ToString()); } } |
|||
60
Serginio1
21.05.13
✎
12:57
|
void ExternalEvent1С()
{ try { EventTo1C.SetEventBufferDepth(4096); EventTo1C.ExternalEvent("ДанныеПоTCP", "Команда", ""); } catch (Exception e) { ЗаписатьОшибку(DateTime.Now.ToString() + e.ToString()); } } Из 1С доступ к данным через свойство public string ДанныеДляКоманды{get{return данныеДляКоманды;}} так как есть ограничение на строку во третьем параметре. Хотя можно побороть с помощью SetEventBufferDepth но проще доступ из 1С к свойству |
|||
61
Serginio1
21.05.13
✎
12:59
|
Ну и соответственно если есть ответ
public void Ответить(string Ответ) { Otvet = Ответ; Event.Set(); } |
|||
62
oleg_km
21.05.13
✎
13:43
|
(60)-(62) Да нет так я могу написать и активикс. Мне хочется не писаь код шарпе, а весь код писать в 1С, например:
Процедура TCPServerНажатие(Элемент) обСокет = Плагин.СоздатьОбъект(Плагин.ПолучитьТип("System.Net.Sockets.Socket", "System"), Плагин.ПолучитьТип("System.Net.Sockets.AddressFamily", "System").InterNetwork, Плагин.ПолучитьТип("System.Net.Sockets.SocketType", "System").Stream, Плагин.ПолучитьТип("System.Net.Sockets.ProtocolType", "System").Tcp); // Точка = Плагин.СоздатьОбъект(Плагин.ПолучитьТип("System.Net.IPEndPoint", "System"), // Плагин.ПолучитьТип("System.Net.IPAddress", "System").Any, 9000); Точка = Плагин.СоздатьОбъект(Плагин.ПолучитьТип("System.Net.IPEndPoint", "System"), 0, 9000); обСокет.Bind(Точка); обСокет.Listen(10); ТипСобытия = Плагин.ПолучитьТип("System.Net.Sockets.SelectMode", "System"); Для ии = 1 По 10 Цикл Сообщить("Ожидание: " + Число2Стр(ии)); Рез = обСокет.Poll(10 * 1000000, ТипСобытия.SelectRead); Если НЕ Рез Тогда Сообщить(Символы.Таб + "Тайм аут подключения"); Продолжить; КонецЕсли; обНовыйСокет = обСокет.Accept(); Сообщить(Символы.Таб + "Соединение: " + обНовыйСокет.LocalEndPoint.Address.ToString() + "/" + Число2Стр(обНовыйСокет.LocalEndPoint.Port) + " => " + обНовыйСокет.RemoteEndPoint.Address.ToString() + "/" + Число2Стр(обНовыйСокет.RemoteEndPoint.Port)); мсДанные = Плагин.ПолучитьТип("System.Text.Encoding").Default.GetBytes("Hello:" + Символы.ВК + Символы.ПС); обНовыйСокет.Send(мсДанные); Рез = обНовыйСокет.Poll(10 * 1000000, ТипСобытия.SelectRead); Если Рез Тогда мсРез = Плагин.СоздатьМассив(Плагин.ПолучитьТип("System.Byte"), обНовыйСокет.Available); обНовыйСокет.Receive(мсРез); Сообщить(Символы.Таб + "Принято: " + Плагин.ПолучитьТип("System.Text.Encoding").Default.GetString(мсРез)); КонецЕсли; Сообщить(Символы.Таб + "Закрываю"); обНовыйСокет.ShutDown(Плагин.ПолучитьТип("System.Net.Sockets.SocketShutdown", "System").Both); обНовыйСокет.Close(); КонецЦикла; // обСокет.ShutDown(Плагин.ПолучитьТип("System.Net.Sockets.SocketShutdown", "System").Both); обСокет.Close(); КонецПроцедуры Вот, весь код написан в 1С, не нужно обновлять сборку, перераспространять ее. Один раз установить класс-обертку, а дальше все на стороне 1С. Вот еще добавить как-то создание делегата на базе метода объекта 1С (?) и функцию установить этот делегат событию нужного объекта. Это вообще возможно? Мой уровень познания шарпа не дает возможности оценить. |
|||
63
Serginio1
21.05.13
✎
13:55
|
(62) Только на обНовыйСокет.Poll 1С будет заморожена.
Все же сервер должен работать в ассинхронном режиме. можешь попробовать события http://stackoverflow.com/questions/10052722/manage-activex-net-event-by-javascript |
|||
64
Serginio1
21.05.13
✎
14:01
|
(62) Ты можешь передать в свою библиотеку общий модуль.
Например На Шарпе есть Свойство dinamic Модуль1С {get;set;} Из 1С установи это свойство. ШарпОбъект.Модуль1С=ОбщегоНазначения; Из Шарпа вызывай Модуль1С.ВнешнееСобытие() Метод ВнешнееСобытие должен быть в модуле ОбщегоНазначения |
|||
65
oleg_km
21.05.13
✎
14:06
|
(63)(64) Это мне все понятно, это я уже делал. Но это предполагает необходимость написания кода как в конфигурации 1С, так и в проекте на шарпе. Я же хочу, чтобы проект на шарпе был просто универсальной оберткой и больше не менялся, а весь нужный код, в том числе и дотнетный дописывался на 1С, как (62).
|
|||
66
Serginio1
21.05.13
✎
14:20
|
(65) А зачем так извращаться то? Сом библиотеку легче написать.
Эта обертка хороша для готового класса с использованием кучей классов не использующих ComVisible = true. |
|||
67
Serginio1
21.05.13
✎
14:24
|
Даже так AutoWrap больше нужен внутри Net что бы выдавать на сторону 1С Idispatch обертку.
|
|||
68
Serginio1
21.05.13
✎
14:28
|
Для делегатов можешь использовать свой сборки с классами специально сгенеренными под задачу, но будет ничем не лучше создания Com библиотеки
|
|||
69
oleg_km
21.05.13
✎
14:32
|
(67) Ну я просто хотел решить организационную задачу: развивать проект, только на стороне кода 1С. А в шарп не лазить вообще. Написать суперуниверсальную обертку и дальше кодить на стороне 1С. Ну нет, так нет. Все равно еще нужно обращение к DLLImport. Поэтому решил для событий сделаю специализированные актисИскы, для DLLImport сделаю спецклассы, все остальное буду дергать через обертку. Всяко легче будет
|
|||
70
Serginio1
21.05.13
✎
15:03
|
(69) Ну можешь конечно посмотреть в сторону CSharpCodeProvider
http://www.gotdotnet.ru/blogs/olegaxenow/6520 http://msdn.microsoft.com/en-us/library/microsoft.csharp.csharpcodeprovider.aspx Но это опять ничем не будет лучше чисто нетовских сборок. Но я никак не вижу премущества перед Сом объектом. Но тут уж хозяин барин. |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |