Как создать и использовать только "Сборочную сборку" только для метаданных?
Начиная с версии 3.0,.NET устанавливает множество различных "сборочных сборок" в разделе C:\Program Files\Reference Assemblies\Microsoft.... для поддержки разных профилей (например, профиль клиента .NET 3.5, профиль Silverlight). Каждая из них является подходящей сборкой .NET, которая содержит только метаданные - не IL-код, и каждая сборка помечена ReferenceAssemblyAttribute
. Метаданные ограничены теми типами и членами, доступными в соответствии с применимым профилем, - что как intellisense показывает ограниченный набор типов и членов. Ссылочные сборки не используются во время выполнения.
Я немного узнал об этом из этого сообщения в блоге.
Я хотел бы создать и использовать такую ссылочную сборку для своей библиотеки.
- Как создать сборку только для метаданных - есть ли какой-нибудь флаг компилятора или постпроцессор ildasm?
- Существуют ли атрибуты, которые управляют тем, какие типы экспортируются в разные "профили"?
- Каким образом разрешение ссылочной сборки во время выполнения - если бы у меня была ссылочная сборка, присутствующая в моей директории приложений, а не в "реальной" сборке, а не в GAC вообще, прощупывание продолжалось бы и событие AssemblyResolve, чтобы я может поставлять фактическую сборку во время выполнения?
Любые идеи или указатели на то, где я мог бы узнать больше об этом, будут очень признательны.
Обновление. Оглядываясь немного, я вижу, что сборщики ссылок .NET 3.0, похоже, имеют некоторый код, а атрибут Reference Assembly был добавлен только в .NET 4.0. Таким образом, поведение может немного измениться с новой средой выполнения.
Почему? Для моей библиотеки Excel-DNA (http://exceldna.codeplex.com) я создаю однодоменную надстройку .xll, упаковывая ссылочные сборки в файл .xll как Ресурсы. Упакованные сборки включают пользовательский код надстройки, а также управляемую библиотеку Excel-DNA (на которую может ссылаться сборка пользователя).
Это звучит довольно сложно, но в большинстве случаев он прекрасно работает - надстройка представляет собой один небольшой файл, поэтому нет установки проблем с дистрибутивом. Я сталкиваюсь с (не неожиданными) проблемами из-за разных версий - если в качестве файла старой управляемой библиотеки Excel-DNA есть старая версия, среда выполнения загрузит это вместо упакованного (я никогда не получаю возможность помешать загрузка).
Я надеюсь создать ссылочную сборку для моей управляемой Excel-ДНК части, которую пользователи могут указать при компиляции своих надстроек. Но если они ошибочно имеют версию этой сборки во время выполнения, среда выполнения должна не загружать ее и дать мне возможность загрузить реальную сборку из ресурсов.
Ответы
Ответ 1
Чтобы создать ссылочную сборку, вы должны добавить эту строку в свой файл AssemblyInfo.cs
:
[assembly: ReferenceAssembly]
Чтобы загрузить других, вы можете ссылаться на них как обычно из ваших проектов проекта VisualStudio или динамически во время выполнения, используя:
Assembly.ReflectionOnlyLoad()
или
Assembly.ReflectionOnlyLoadFrom()
Если вы добавили ссылку на сборку метаданных/ссылок, используя VisualStudio, то intellisense и создание вашего проекта будут работать нормально, однако если вы попытаетесь выполнить свое приложение против одного, вы получите сообщение об ошибке:
System.BadImageFormatException: не удается загрузить контрольную сборку для выполнения.
Итак, ожидание заключается в том, что во время выполнения вы заменили бы в реальной сборке, имеющей одну и ту же подпись метаданных.
Если вы динамически загрузили сборку с помощью Assembly.ReflectionOnlyLoad()
, вы можете выполнять только все операции отражения против нее (читайте типы, методы, свойства, атрибуты и т.д., но не можете динамически вызывать их).
Мне интересно, что вы используете для создания сборки только для метаданных. Мне никогда не приходилось делать это раньше, и мне было бы интересно узнать, нашли ли вы для них интересное использование...
Ответ 2
Если вы по-прежнему заинтересованы в этой возможности, я создал вилку проекта il-repack на основе Mono.Cecil, который принимает аргумент командной строки "/meta", чтобы создать сборку только для метаданных для публичных и защищенных типы.
https://github.com/KarimLUCCIN/il-repack/tree/xna
(Я попробовал это на полной платформе XNA Framework и ее рабочем афайке...)
Ответ 3
Да, это ново для .NET 4.0. Я уверен, что это было сделано, чтобы избежать неприятных проблем с версиями в пакетах обновления .NET 2.0. Лучший пример - перезагрузка WaitHandle.WaitOne(int), добавленная и документированная в SP2. Популярная перегрузка, потому что она позволяет избежать угадывания правильного значения для * exitContext в перегрузке WaitOne (int, bool). Проблема в том, что программа бомбит, когда она запускается на версии 2.0, которая старше SP2. Кроме того, изолирование эталонных сборок гарантирует, что это не повторится.
Я думаю, что эти сборки ссылок были созданы, начиная с копии скомпилированных сборок (как это было сделано в предыдущих версиях) и запускали их через инструмент, который удаляет IL из сборки. Однако этот инструмент недоступен для нас, ничего не найдено в подкаталоге bin/netfx 4.0 под Windows 7.1 SDK, который мог бы это сделать. Не совсем инструмент, который часто используется, поэтому, вероятно, это не качество продукции:)
Ответ 4
Возможно, вам повезло с Cecil Library (от Mono); Я думаю, что реализация позволяет ILMerge функциональность, она может так же хорошо писать метаданные только сборки.
Я просмотрел базу кода (документация разрежена), но пока не найдено никаких очевидных подсказок...
YYMV