Преобразование сборок .NET в сборки Silverlight

ОГЛАВЛЕНИЕ

Демонстрация преобразования сборок .NET в сборки Silverlight

Введение

Данная статья решает проблему, представленную Дэвидом Бетзом в своей статье Повторное использование сборок .NET в Silverlight, путем создания простого консольного приложения, запускаемого в послесборочных командах.

Краткая информация

Теперь, когда вышла вторая версия Silverlight, используемая растущим числом разработчиков, на основе каркаса разрабатываются более продвинутые приложения.

Одной из эффективных особенностей Silverlight является возможность его соединения с сервисами WCF(основы связи Windows). Так как большинство разработчиков решает реализовать контрактные классы в открытой сборке, на которую затем ссылаются конструктор сервиса и клиент, проблема возникает при попытке сослаться на эту открытую сборку через приложение Silverlight.

Не будем разбирать подробно, почему Visual Studio не дает добавлять не? Silverlight сборки в проект Silverlight, так как это детально представлено в статье Дэвида Бетза. Но вкратце, сборки, используемые Silverlight (System.dll, mscorlib.dll etc.), не являются точно такими же, как и основные сборки .NET, хотя многие функции есть и в тех, и в других. Сборки Silverlight являются сокращенной версией полных сборок .NET, но  и те, и другие почти одинаковы по предоставляемым функциям.
По сути, если изменить открытую сборку так, чтобы она ссылалась на Silverlight-версию этих сборок без изменения кода, то можно повторно использовать открытую сборку в приложении Silverlight.

Сборки MSIL

Когда вы пишете код на любом языке .NET (C#, VB.NET), компилятор компилирует код в то, что называется MSIL, или промежуточный язык Microsoft. Затем этот код собирается в сборку .NET, загружаемую и динамически компилируемую во время выполнения. Так как ссылки сборки проверяются лишь во время выполнения, можно безопасно менять ссылки спорных сборок на правильные сборки Silverlight в коде IL, и когда сборка загружается посредством Silverlight, правильные сборки уже будут находиться в памяти, и динамичный компилятор скомпилирует код в зависимости от них.

Цель

После того как сборка собрана, надо снова разобрать ее в MSIL, внести несколько изменений в ссылки (возможно, удалить некоторые атрибуты, не поддерживаемые Silverlight-версией ссылок), и вновь собрать код в новую сборку, которую способен использовать Silverlight.

Замечание: вновь созданная сборка может использоваться лишь из проекта Silverlight, но все сигнатуры типов будут тождественны исходной сборке, поэтому можно будет делиться контрактами WCF между обоими.

Создание приложения

Включенный код – простое консольное приложение, написанное на C#. Его сопровождает XML файл, содержащий все настройки, необходимые ему для запуска.

Приложению надо знать следующую информацию:
1.    Расположение ассемблера и дизассемблера MSIL (ilasm.exe и ildasm.exe).
2.    Список сборок, меняющихся между их реализацией Silverlight и их аналоги .NET.
3.    Список любых неподдерживаемых атрибутов, расположенных в исходных сборках .NET, и тех, которые не существуют в Silverlight и должны быть удалены из кода IL.

Файл XML выглядит так:

<?xml version="1.0" encoding="utf-8" ?>
<SLAsm.Settings xmlns="urn:Silverlight-Assmblies/SLAsmSettings.xsd"
    ILAssembler="C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\ilasm.exe"
    ILDisassembler="C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\ildasm.exe">
     <ExternAssembly Name="System" Version="2.0.5.0"
         PublicKeyToken="7C EC 85 D7 BE A7 79 8E" />
     <ExternAssembly Name="mscorlib" Version="2.0.5.0"
         PublicKeyToken="7C EC 85 D7 BE A7 79 8E" />
     <ExternAssembly Name="System.Core" Version="2.0.5.0"
         PublicKeyToken="7C EC 85 D7 BE A7 79 8E" />
     <ExternAssembly Name="System.Net" Version="2.0.5.0"
         PublicKeyToken="7C EC 85 D7 BE A7 79 8E" />
     <ExternAssembly Name="System.Runtime.Serialization"
         Version="2.0.5.0" PublicKeyToken="7C EC 85 D7 BE A7 79 8E" />
     <ExternAssembly Name="System.Windows"
         Version="2.0.5.0" PublicKeyToken="7C EC 85 D7 BE A7 79 8E" />
     <ExternAssembly Name="System.Json"
         Version="2.0.5.0" PublicKeyToken="31 BF 38 56 AD 36 4E 35" />
     <ExternAssembly Name="System.ServiceModel"
         Version="2.0.5.0" PublicKeyToken="31 BF 38 56 AD 36 4E 35" >
          <UnsupportedAttribute>
            System.ServiceModel.FaultContractAttribute
          </UnsupportedAttribute>
          <UnsupportedAttribute>
            System.ServiceModel.DeliveryRequirementsAttribute
          </UnsupportedAttribute>
          <UnsupportedAttribute>
            System.ServiceModel.CallbackBehaviorAttribute
          </UnsupportedAttribute>
          <UnsupportedAttribute>
            System.ServiceModel.MessageHeaderAttribute
          </UnsupportedAttribute>
          <UnsupportedAttribute>
            System.ServiceModel.MessageHeaderArrayAttribute
          </UnsupportedAttribute>
          <UnsupportedAttribute>
            System.ServiceModel.MessagePropertyAttribute
          </UnsupportedAttribute>
          <UnsupportedAttribute>
            System.ServiceModel.OperationBehaviorAttribute
          </UnsupportedAttribute>
          <UnsupportedAttribute>
            System.ServiceModel.ServiceBehaviorAttribute
          </UnsupportedAttribute>
          <UnsupportedAttribute>
            System.ServiceModel.XmlSerializerFormatAttribute
          </UnsupportedAttribute>
          <UnsupportedAttribute>
            System.ServiceModel.PeerHopCountAttribute
          </UnsupportedAttribute>
          <UnsupportedAttribute>
            System.ServiceModel.TransactionFlowAttribute
          </UnsupportedAttribute>
          <UnsupportedAttribute>
            System.ServiceModel.Activation.AspNetCompatibilityRequirementsAttribute
          </UnsupportedAttribute>
     </ExternAssembly>
</SLAsm.Settings>

Не забудьте задать правильные пути в файлах ILAsm.exe и ILdasm.exe

Файл был предварительно заполнен всеми ссылками на сборки Silverlight, и список неподдерживаемых атрибутов был добавлен в сборку System.ServiceModel.

Замечание: это не полный список неподдерживаемых атрибутов, лишь те, с которыми мы столкнулись. Добавляйте любые атрибуты, не работающие с Silverlight. (Приложение Silverlight генерирует TypeLoadException при попытке загрузить сборку.)


Использование кода

Создав файл XML, используем код. Приложение является простым консольным приложением, принимающим следующие аргументы:

<AssemblyPath.dll> [/Key=<StrongNameKeyPath.snk>] [/Output=<TargetPath.dll>]

где AssemblyPath.dll – путь к открытой сборке .NET. Необязательный параметр /Output задает место сохранения новой сборки Silverlight. (Если не указать его, то выходной файл будет AssemblyPath.SL.dll.)

Наконец, так как мы испортили весь исходный код IL, если исходная сборка была подписана ключом со строгим именем, вновь созданная сборка не будет должным образом подписана, поэтому добавьте путь в исходный файл .snk, используемый для подписания сборки, и приложение снова соберет все вместе.

Создание события после сборки

Лучший способ обеспечить преобразование вашей открытой сборки в совместимую с Silverlight и обновление ее при любом изменении – добавить команду 'После Сборки' в ваш проект. Чтобы сделать это, щелкните правой кнопкой мыши по вашему проекту и щелкните по пункту меню «Свойства проекта».

Перейдите во вкладку 'События сборки':

Теперь щелкните по команде 'Редактировать после сборки', и откроется диалоговое окно:

Введите путь к приложению-преобразователю с последующим макросом "$(TargetPath)", чтобы указать собранную сборку в качестве файла, который будет преобразован. Добавьте любые необходимые дополнительные аргументы (такие как /Output= и /Key=) и нажмите на 'OK'.

Убедитесь, что во вкладке 'События сборки' параметру 'Запустить событие после сборки:' задан 'После успешной сборки'. Сохраните проект. После этого во всех случаях успешной сборки проекта Visual-Studio будет запускать приложение и создавать совместимую с Silverlight сборку проекта.

Замечание: если создать совместимую сборку не удастся, весь проект будеn помечен как 'Cборка провалилась', и в окне вывода вы увидите сообщение об ошибке, возвращенное ilasm.exe.

Заключение

Надеемся, статья поможет тем, кто столкнулся с аналогичной проблемой.