14.02.2017, 09:18 | #1 |
Участник
|
runbuf на сервере
Всем привет.
Есть одна не большая задача. Я нашёл один путь её решения, но возможно такую же задачу кто-то решал и нашёл другой путь. Итак, у нас есть несколько сайтов, возвращающих рублёвый курс валюты: юань - XXX.XXX.XXX.XXX:8081 евро - XXX.XXX.XXX.XXX:8082 доллар - XXX.XXX.XXX.XXX:8083 У каждого сайт есть описанный WSDL с одинаковой функцией getCurrency. Все эти сайты не "наши" и попросить "их" сделать как-то по другому - нельзя. Один раз в сутки, карета превращается в тыкву и меняет свой адрес на YYY.YYY.YYY.YYY и каждый раз этот ip новый. Сама задача - хочется автоматически в серверном режиме менять настройки данных адресов. Для начала создадим описание наших WSDL: Нам присылают текстовый файл, с текущими IP, обходим его в цикле и создаём ServiceReference вот такими строчками: X++: SysReference::createServiceReference('CurrencyU', 'XXX.XXX.XXX.XXX:8081?WSDL', 'CurrencyU', 'юань'); SysReference::createServiceReference('CurrencyE', 'XXX.XXX.XXX.XXX:8082?WSDL', 'CurrencyE', 'евро'); SysReference::createServiceReference('CurrencyD', 'XXX.XXX.XXX.XXX:8083?WSDL', 'CurrencyD', 'доллар'); Теперь мы сможем к ним обратиться таким кодом: X++: CurrencyU.AxCurrencyTypeClient webService = new CurrencyU.AxCurrencyTypeClient("AxCurrencySoap"); currentCurrency = webService.getCurrency(); X++: string command = '%1 webService = %1("AxCurrencySoap");'; currentCurrency = webService.getCurrency(); runBuf(command, 'CurrencyU.AxCurrencyTypeClient'); В результате написал код, который в X++ изменяет метод возврата объектов, т.е. есть класс Currency, и у него есть метод getReference, который генерируется автоматически, по приблизительно следующему коду: X++: classBuild = new ClassBuild(classStr(Currency), true); getServiceReference = '// Внимание! Данный метод генерируется автоматически Currency::buildReferences()' + '\n' + 'public static server object getServiceReference(str _referenceName)' + '\n' + '{' + '\n' + ' Object object;' + '\n' + ' ;' + '\n'; while select currencies { getServiceReference += ' case "' + currencies.ServiceReferenceName +'" :' + '\n' + ' object = new ' + currencies.ServiceReferenceName + '.AxCurrencyPortTypeClient("AxCurrencySoap");' + '\n' + ' break;' + '\n'; } getServiceReference += ' }' + '\n'; } getServiceReference += ' return object;' + '\n' + '}'; classBuild.overrideMethod('getServiceReference', getServiceReference); P.S. Это только общий смысл и код приведён лишь частично. Последний раз редактировалось Avalon; 14.02.2017 в 09:26. |
|
14.02.2017, 09:54 | #2 |
Участник
|
вы бы указали версию аксапты.
судя по тому, что на клиенте выполняется, а на сервере нет, то у вас меньше акс2012. начиная с акс4.0 ввели Secure API и специальные permissions на выполнение некоторых операций в коде. в частности, для выполнения runbuf требуется явно получить ExecutePermission в CodeAccessPermission см: https://msdn.microsoft.com/en-us/library/aa656300.aspx https://msdn.microsoft.com/en-us/lib...ermission.aspx https://msdn.microsoft.com/en-us/lib...ermission.aspx https://msdn.microsoft.com/en-us/library/aa852189.aspx |
|
14.02.2017, 10:01 | #3 |
Участник
|
и еще.
не создавайте строки в таком стиле - у вас сборщик мусора с ума сходит от такого. Цитата:
X++: getServiceReference =
@'// Внимание! Данный метод генерируется автоматически Currency::buildReferences()
public static server object getServiceReference(str _referenceName)
...
...
...'; Помогите найти: Сравнение производительности различных операндов при конкатенации строк |
|
14.02.2017, 10:15 | #4 |
Участник
|
и еще... извините.
это вам только кажется, что вы сделали универсальное решение, которое позволяет работать с любыми строчками. Цитата:
если в коде только 3 (три) класса, то другие строчки приведут к ошибке в runtime. другими словами, вы нисколько не приблизились к универсальности. зато: = перевели все ошибки в runtime = сильно затруднили диагностику ошибок (теперь будет выдаваться ошибка компиляции вместо ошибки "неправильная строка") = сильно затруднили себе жизнь с runbuf, правами и обвязкой для таких задач делают семейство классов с construct в construct передают параметр и явно пишут что он может создавать. когда добавляется новый класс наследник, программист должен будет расширить construct в базовом классе. это паттерн, который используется повсеместно во всей аксапте. поищите в коде примеры |
|
14.02.2017, 11:36 | #5 |
Участник
|
1. XppCompiler - не может в CIL.
2. Делайте DLL на C#, в которой используйте ConfigurationChannelFactory, - ей можно отдать endpoint address c нужным вам URL'ом (IP) |
|
|
За это сообщение автора поблагодарили: Logger (5). |
14.02.2017, 12:14 | #6 |
Участник
|
Цитата:
Сообщение от mazzy
вы бы указали версию аксапты.
судя по тому, что на клиенте выполняется, а на сервере нет, то у вас меньше акс2012. начиная с акс4.0 ввели Secure API и специальные permissions на выполнение некоторых операций в коде. в частности, для выполнения runbuf требуется явно получить ExecutePermission в CodeAccessPermission |
|
14.02.2017, 12:17 | #7 |
Участник
|
Спасибо, это я всё знаю, но по факту, данный код будет выполняться 1-2 раза в году (а может и меньше), а мне в данном случае мне удобней писать именно так.
|
|
14.02.2017, 12:21 | #8 |
Участник
|
Цитата:
Сообщение от mazzy
и еще... извините.
это вам только кажется, что вы сделали универсальное решение, которое позволяет работать с любыми строчками. на самом деле у вас доступны только те значения, для которых есть классы в коде. если в коде только 3 (три) класса, то другие строчки приведут к ошибке в runtime. другими словами, вы нисколько не приблизились к универсальности. зато: = перевели все ошибки в runtime = сильно затруднили диагностику ошибок (теперь будет выдаваться ошибка компиляции вместо ошибки "неправильная строка") = сильно затруднили себе жизнь с runbuf, правами и обвязкой для таких задач делают семейство классов с construct в construct передают параметр и явно пишут что он может создавать. когда добавляется новый класс наследник, программист должен будет расширить construct в базовом классе. это паттерн, который используется повсеместно во всей аксапте. поищите в коде примеры |
|
14.02.2017, 12:22 | #9 |
Участник
|
|
|
14.02.2017, 12:45 | #10 |
Участник
|
|
|
14.02.2017, 13:03 | #11 |
Moderator
|
Есть еще более примитивное решение:
1. В \windows\system32\driver\etc\hosts добавляем строчку вида "ourWFCServer XXX.XXX.XXX.XXX" (Где xxx.. - текущий адрес сервера на момент генерации). 2. генерируем Service Reference для адреса ourWCFServer. 3. Пишем отдельный батч, который при получении нужного файла с адресами, правит этот самый hosts-файл. |
|
|
За это сообщение автора поблагодарили: MazZzDaI (1). |
14.02.2017, 13:26 | #12 |
Участник
|
Не поленитесь, создайте класс-обертку для каждого вашего класса CurrencyU и пр. Сделайте их наследниками общего класса с вашей функцией getCurrency() и обойдитесь без runBuf().
Цитата:
Использование strFmt() - это не просто еще один способ, это общемировая практика. Речь идет даже не о производительности, а о понимании вас другими разработчиками. И в вашем случае не важно сколько раз в году этот код будет выполняться, а то, сколько людей будет модифицировать ваш код и поносить ваше имя так, что уши гореть будут.
__________________
// no comments |
|
14.02.2017, 14:12 | #13 |
Участник
|
Цитата:
Сообщение от fed
Есть еще более примитивное решение:
1. В \windows\system32\driver\etc\hosts добавляем строчку вида "ourWFCServer XXX.XXX.XXX.XXX" (Где xxx.. - текущий адрес сервера на момент генерации). 2. генерируем Service Reference для адреса ourWCFServer. 3. Пишем отдельный батч, который при получении нужного файла с адресами, правит этот самый hosts-файл. |
|
14.02.2017, 14:14 | #14 |
Участник
|
Цитата:
Сообщение от dech
Не поленитесь, создайте класс-обертку для каждого вашего класса CurrencyU и пр. Сделайте их наследниками общего класса с вашей функцией getCurrency() и обойдитесь без runBuf().
Это путь к одиночеству. Тем более, что если вы все и так знаете, но вам "удобнее" по-другому. Использование strFmt() - это не просто еще один способ, это общемировая практика. Речь идет даже не о производительности, а о понимании вас другими разработчиками. И в вашем случае не важно сколько раз в году этот код будет выполняться, а то, сколько людей будет модифицировать ваш код и поносить ваше имя так, что уши гореть будут. |
|
14.02.2017, 14:22 | #15 |
Участник
|
Цитата:
Нет здесь неизвестных объектов и не нужно здесь динамического программирования. Но опять же: хозяин - барин. |
|
14.02.2017, 14:23 | #16 |
Участник
|
|
|
|
За это сообщение автора поблагодарили: dech (2). |
15.02.2017, 08:01 | #17 |
Участник
|
Изначальная интерпретация задачи:
Цитата:
Цитата:
__________________
// no comments |
|
15.02.2017, 08:12 | #18 |
Участник
|
скорее всего, программисты на этой стороне (свои программисты) не знают измененные ip-адреса
скорее всего, смена ip-адресов является что-то вроде защиты платного сервиса - где-то в платной области есть постоянный адрес и редирект на новый ip-адрес. скорее всего, ответственные пользователи не захотели оплачивать этот платный сервис, а напрягли "своих" программистов. скорее всего, "свои" программисты в качестве своеобразной мести заставили пользователей вводить адреса, а пользователи в отместку "присылают текстовый файл" непонятного формата. вот! ключевое слово "список". можно даже сказать - постоянный список. элементы в этом списке далеко не произвольные. элементы в этот список добавляются очень редко. добавление в этот список связано с обязательным созданием нового класса в аксапте. переменной частью в этом списке является только адреса. динамическое программирование для такой задачи не нужно. Скрипач не нужен, Дядя Вова. Последний раз редактировалось mazzy; 15.02.2017 в 08:15. |
|
15.02.2017, 09:10 | #19 |
Участник
|
Собственно, задача вообще к валюте никакого отношения не имеет, это был лишь завуалированный пример. Всем проще прицепиться к тому, что "фары не протёр", вместо того, чтобы понять почему двигатель не заводится. В любом случае всем спасибо, видимо других решений просто нет.
|
|
15.02.2017, 09:25 | #20 |
Участник
|
Можно, конечно, предусмотрительно сгенерировать своего рода радужную таблицу сервисов для всех адресов, их около 4.22 млрд.
|
|