Category Archives: .NET

Microsoft порадовал

Written by elwood

VisualStudio2013

На днях вычитал о вышедшей новой Visual Studio 2013 RC. Решил попробовать установить, чтобы проверить, пофиксили ли окончательно проблему с XAML-дизайнером. Проблема была в том, что наши WPF-приложения, использующие для организации UI-кода концепцию MVP (Model-View-Presenter), в базовых классах для Windows и UserControls использовали Generic-классы: ConcreteWindow: BaseWindow<TModel, TPresenter, TView>, где TModel – тип-аргумент класса модели (автоматически становится DataContext’ом), TPresenter – соответственно, класс презентера, и TView – интерфейс представления, реализуемого окном. Презентер имеет доступ к модели и к представлению (через интерфейс), представление работает с моделью посредством байндингов. Модель не знает ни о чем, кроме себя, хранит данные и оповещает об их изменении. Всё стандартно. И в старых версиях Visual Studio всё работало на ура, однако в 2012 версии майкрософтовцы перефигачили дизайнер (видимо, взяв код из Blend, поскольку там раньше наблюдалась такая же проблема), и отображение таких XAML (у которых главный элемент определяет generic-класс) отвалилось. При этом проект продолжал собираться и работать, и по спецификациям XAML всё было в порядке. Мои товарищи по несчастью тогда запостили вышеприведённый тред, и вскоре проблему вроде бы пофиксили, но, когда я установил себе обновление, всё осталось по-прежнему. Вчера я решил вновь побороться за улучшение мира, и отписался их “програм менеджеру”, рассказав свою душещипательную историю и приложив архив тестового проекта, воспроизводящего проблему. Сегодня мне пришел ответ:

microsoft-reply

Как оказалось, действительно достаточно убрать пробелы, и всё заработает ! В общем, я очень обрадовался, во-первых, быстрому ответу, а во-вторых тому, что мои изобретения снова можно использовать в современных Visual Studio. А то после неудач с 2012 студией мне казалось, что этот подход теперь будет нежизнеспособен, придется самому переезжать на традиционный MVVM, и уж точно никто из других людей не будет пользоваться технологией, которая не совместима с XAML-дизайнером. Теперь хотя бы есть надежда, что эти наработки не умрут. Собираюсь выложить их в открытый доступ, поскольку для наших проектов они оказались довольно удачным способом организации кода.

NBox 1.0 released

Written by elwood

Untitled

Собрался с силами и зарелизил свою давно написанную утилиту для запаковки бинарников в один исполняемый файл. Попутно проверил работоспособность основных кейсов, добавил пару примеров (в том числе пример с нативной DLL, проигрывающей XM файл). А то проект вроде рабочий, но воспринимается как мертвый из-за последнего релиза 3 года назад.

Соединяем Java и .NET: jni4net

Written by elwood

jni4net143x123 Наша система, написанная на Java, должна взаимодействовать с коллцентром. Коллцентр – это такая десктопная приложуха, которая запускается на компьютере отдельно и принимает звонки клиентов. Приложение это предоставляет COM-интерфейсы для взаимодействия с ней, можно получить текущий статус, подключиться к серверу и подписаться на события поступления звонков. Так как взаимодействовать с COM удобнее всего на дотнете, то решили действовать именно так. Но основное-то наше приложение – это десктопный Swing-клиент! Нужно как-то транслировать всю информацию из дотнетовой аппликухи в свинговую. Два года назад такая же проблема была решена путём взаимодействия через сеть. Дотнетовое приложение тогда запускалось отдельно и при некоторых событиях дёргало по HTTP некий урл, который уже обрабатывался Java-программой. Но сейчас мы обнаружили такую замечательную штуку как jni4net. Этот opensource инструмент, написанный энтузиастом, позволяет внутри Java-процесса загружать дотнетовую CRL и работать напрямую с дотнетовыми классами через JNI. Для дотнетовых классов будут сгенерированы удобные Java-прокси классы, которые вы сможете вызывать так, как будто это были бы обычные Java классы. Но при этом все вызовы будут затранслированы в дотнетовский рантайм. То же самое можно проделать и в другом направлении – то есть внутри CLR подгрузить Java Runtime и обращаться к JVM аналогичным образом. Поковырявшись немного, хочу тезисно расписать основные моменты, на которых бы хотелось остановиться:

  1. Это реально работает!
  2. Чтобы создать ant-скрипт для сборки такой конструкции, пришлось повозиться, но я подготовил шаблон проекта, с которого можно начать быстро и безболезненно.
  3. В случае вызова .NET из контекста работающего Java-процесса все происходит примерно следующим образом: jni4net загружает DLL-переходник для CLR соответствующей разрядности, затем происходит загрузка CLR, после этого грузится ваша DLL.
  4. Дотнетовые поля не маршаллятся (в прокси-классах их просто не будет), используйте свойства.
  5. Свойства маршаллятся на ура, превращаясь по ходу дела в геттеры и сеттеры (правда, булевые свойства тоже будет доступны через get, а не через is, как многие привыкли видеть).
  6. Делегаты нужно придумывать свои, поскольку прокси-классы к стандартным скорее всего не будут созданы (для этого наверное нужно более подробно конфигурировать proxygen). То есть просто EventHandler лучше не использовать, можно завести свой public делегат и он прекрасно будет преобразован в интерфейс с методом Invoke(). Соответственно, в Java коде вы создаете свою реализацию этого интерфейса (например, анонимную) – всё как с обычными джавовыми слушателями.
  7. Насчет исключений я не разбирался, вроде бы тоже должны маршаллиться, но я предпочел использовать паттерн “GetLastError”, чтобы не зависеть от этого.
  8. Если ваша DLL требует того, чтобы быть сконфигурированной в App.config- у вас не получится этого сделать. В списках рассылки автор предлагает обходить это двумя путями: либо инициализировать всё программно, либо в вашей DLL уже создавать отдельный AppDomain и в него загружать сборки.
  9. Если вам необходимо работать с 32-разрядными библиотеками (в моём случае это было именно так), то вам придётся позаботиться о том, как настроить запуск вашего java-приложения с 32-битной JVM.
  10. Если вы хотите засунуть все DLL в отдельную папку, вы должны туда же засунуть и jni4net.j-0.8.6.0.jar. Судя по экспериментам, jni4net ищет свой рантайм рядом с собой, определяя местоположение своего джарника. Но при указании библиотеки, которую вы хотите загрузить, вы должны указать путь к ней. Например, так:Bridge.LoadAndRegisterAssemblyFrom(new java.io.File("lib\\net-app.j4n.dll"));

    Если всё, что связано с jni4net лежит в lib. В этом случае jni4net найдет свой рантайм, а также найдет net-app.j4n.dll в месте, которое вы ему указали. Можно ли держать рантайм jni4net в одной папке, а дотнетовые DLL в другой, пока не ясно.

  11. Запуск из папки, расположенной на сетевом диске, не работает – Windows не разрешает загружать дотнетовые сборки из shared-папок по умолчанию. На Windows 7 я получил следующий стектрейс:
    Can't init BridgeExport: DLLs are marked as unsafe. Open file properties in windows explorer and click unblock.
    Can't init BridgeExport:An attempt was made to load an assembly from a network location which would have caused the assembly to be
    sandboxed in previous versions of the .NET Framework. This release of the .NET Framework does not enable CAS policy by default, s
    o this load may be dangerous. If this load is not intended to sandbox the assembly, please enable the loadFromRemoteSources switch
    . See http://go.microsoft.com/fwlink/?LinkId=155569 for more information.
    Can't init BridgeExport:System.NotSupportedException: An attempt was made to load an assembly from a network location which would
    have caused the assembly to be sandboxed in previous versions of the .NET Framework. This release of the .NET Framework does not e
    nable CAS policy by default, so this load may be dangerous. If this load is not intended to sandbox the assembly, please enable th
    e loadFromRemoteSources switch. See http://go.microsoft.com/fwlink/?LinkId=155569 for more information.
    at System.Reflection.RuntimeAssembly.nLoadFile(String path, Evidence evidence)
    at System.Reflection.Assembly.LoadFile(String path)
    at net.sf.jni4net.BridgeExport.initDotNet(IntPtr envi, IntPtr clazz)
    Can't initialize jni4net Bridge from S:\temp\elwood\Taxi\lib\jni4net.n.w32.v40-0.8.6.0.dll
    Can't initialize jni4net BridgeCan't initialize jni4net Bridge. Code:-101

    На Windows XP у меня в такой же ситуации просто вылетела JVM. Возможно, есть способ это исправить, но я не исследовал.

 

Ещё раз ссылка на шаблон проекта, который можно взять и запустить:

https://bitbucket.org/igor_kostromin/jni4net-app-template