Как заставить InternalsVisibleTo работать, когда процесс сборки подписывает сборку строгими именами?
В нашем магазине мы используем Cruise Control и MSBuild для автоматизации сборок продукта в рамках непрерывной интеграции.
Часть сборки должна подписывать сборки, чтобы они имели строгие имена.
В наших файлах проекта, когда мы разрабатываем локально, в нем не указывается подпись, так как это отменяется сценарием MSBuild.
Это все хорошо, пока я не решил ввести модульные тесты, которые требуют от меня использования InternalsVisibleTo
приписывать. Я также начал использовать хорошую библиотеку с открытым исходным кодом, в которой есть модульные тесты, которые также используют эту технику.
Это означает, что на моей машине я могу обновить AssemblyInfo.cs
использовать следующее утверждение:
[assembly: InternalsVisibleTo("MyProject.Tests.UnitTests")]
и все хорошо.
Однако проверка этого прерывает сборку, так как сборочный компьютер подписывает сборки, поэтому необходимо обновить эту строку, чтобы она выглядела следующим образом:
[assembly: InternalsVisibleTo("MyProject.Tests.UnitTests,
PublicKey="magic key here..)"]
У меня есть полумрака, чтобы не подписывать собрания и называть это днем. Тем не менее, "подписание сборок - это лучшая практика"(повторите эту мантру 3 раза), и если мы получим какую-либо выгоду от этого, я не хочу ее удалять.
Мы не устанавливаем в GAC, нас не особо беспокоит фальсификация, нам не нужно беспокоиться о третьих сторонах, которые используют наши библиотеки, мы обновляем все наши файлы сразу, когда обновляем приложение. Наиболее заметным преимуществом является то, что кто-то из техподдержки не может скопировать случайную версию сборки в папку времени выполнения, и некоторые вещи могут работать некоторое время.
Я не хочу открывать банку с работами, изменяя около 100 файлов проекта вручную, чтобы включить подпись. Я также не хочу взламывать вещи, помечая вещи, которые должны быть внутренними, как публичные, я не хочу связываться с перенаправлениями и не хочу удалять модульные тесты.
Мне бы очень хотелось, чтобы у меня не было сильных имен со всеми преимуществами наличия сильных имен (если они есть), и я не хочу создавать для этого много дополнительной работы. Неужели я прошу так много?
Этот пост хорошо описывает проблему и ее решение, но я не очень разбираюсь в сценарии MSBuild, чтобы воспользоваться этим:
http://social.msdn.microsoft.com/forums/en-US/msbuild/thread/02df643c-956a-48bd-ac01-4a1016d91032/
Как правильно решить эту проблему?
Любые вклады и вопросы для обсуждения приветствуются.
2 ответа
Вы можете добавить информацию о ключе в исходные файлы перед компиляцией.
В следующем примере используется FileUpdate
из задач сообщества MSBuild и (очень грубого) регулярного выражения для вставки ключевой информации в файлы C# AssemblyInfo.cs.
<ItemGroup>
<AssemblyInfoFiles Include="$(MSBuildProjectDirectory)**/AssemblyInfo.cs"/>
</ItemGroup>
<FileUpdate
Files="@(AssemblyInfoFiles)"
Regex='(\[assembly:\s*InternalsVisibleTo\(\"[\w.]*\")(\)\])'
ReplacementText='$1, PublicKey="$(StrongNamingPublicKey)"$2' />
Тем не менее, я думаю, что изменение проектов под всегда строгим именем было бы более чистым решением для устранения еще одного различия между средой разработки и развернутыми средами, и его можно было бы легко написать в сценарии.
Используйте ту же конструкцию, которую вы используете, чтобы отключить подпись сборки разработчика для определения символа компилятора, например. DO_NOT_SIGN, то в вашем AssemblyInfo.cs
, использовать этот:
#if DO_NOT_SIGN
[assembly: InternalsVisibleTo("MyProject.Tests.UnitTests")]
#else
[assembly: InternalsVisibleTo("MyProject.Tests.UnitTests, PublicKey="magic key here..)"]
#endif
По моему личному мнению, это более элегантно, чем изменение исходного кода из скрипта сборки.