Есть C#(.NET) утилитная библиотека, которую нужно включать в проекты собираемые под разными .NET версиями. Например в библиотеке есть код использующий .NET Framework v4.0, а нам нужно включить её в проект для .NET 2.0
11 лет .NET фрэймворку будет 13 февраля 2013 года. Было выпущено целых 7 версий. Создано огромное количество программистов. Решено масса задач, концептуально решено огромное число проблем ставящихся перед программистами.
А вопрос совместимости по прежнему актуален.
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'ReleaseFW3|AnyCPU'">
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;FW3</DefineConstants>
Теперь нужно сделать правильный референс к проектам:
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Runtime.Caching">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="System.Web" />
<Reference Include="System.Xml" />
</ItemGroup>
Вариант 5 мне нравится больше всего? А вам?
Правильно: "купание в море повышает настроение" (с) МЕГА. Айда купаться!
А вопрос совместимости по прежнему актуален.
Понадобилось мне недавно из набора сырцов разношерстных сырцов слепить библитеку. Как-то устаканить их, влить в коде-базу, сделать все цивилизованно. Код разношерстный, часть использует .NET 4, часть зависит от сборки System.Web и масса кода предназначена только для веба и не имеет смысла в desktop приложении, часть является самописными древними полу-аналогами функционала появившегося в .NET 3-4 и не имеющим смысла для поздних версий фрэймворка. Короче: нужно разделять код, делать условную компиляцию, а главное dll с утилитным кодом не должна требовать наличия фрэймворка выше чем солюшин в который она включена или выше чем проэкт её использующий.
На живом примере: у нас есть класс осуществляющий кеширование объектов в памяти.
Последний код скомпилируется везде, но работать будет не так эффективно как первые два и будет менее удобен для программиста. Так как же сделать, чтобы внутри библиотеки был весь этот функционал, но компилятор бы не собирал код и не включал референсы на системные сборки, которые недоступны если мы собираемся для .NET 2.0 например? И включал и использовал функционал для .NET 4 если доступен таковой?
Указание компилятор игнорировать некоторый код у нас идут через директивы препроцессора (кстати, он есть в .NET-e?).
Вспоминаем #define из С/С++ отличная вещь: определяем константы и ветвим код. Замечательно выходит.
Студия при сборке не определяет константу, подсказывающую компилятору версию фрэймворка. Упс. Ладно определим её сами.
#define FW3 //если определана эта коснтанта будет включен код которой работает максимум на третьем фрэймворке.
Парням из MS имело бы смысл унифицировать имена подобных констант.
На всякий случай: #define в .NET действует только на тот файл в котором он определен.
Опять упс. Не сильно удобно. Но идем в настройки проэкта и определяем там константу для препроцессора. Проблема решена?
Нет. Точнее не полностью: мы хардкоднули в проект target framework. Пока у нас dll используется только в одном проекте - всё хорошо. Как только мы начинаем её использовать для разных, приходим к необходимости менять в проекте target framework и переопределять константу для разных солюшенов.
Опытные перцы решают проблему одним из следующих способов:
Первый вариант: утилитные классы в отдельной папке, которую мы просто закидываем в проект
Плюсы: никакого разбирательства с проектами, удобно дебажить
Плюсы: никакого разбирательства с проектами, удобно дебажить
Минусы: необходимость прописывать для всего солюшена малозначащий дефайн для всего остального кода, пересборка всех сырцов каждый раз (тормозит работу, когда утилитного кода много, а его как правило много), сложности с добавлением новых классов, вероятность повяления дублирующего когда разные программисты изобретают один и тот же велосипед.
Такой подход благодаря своей простоте хорошо работает в маленькой команде с малым числом проектов. Когда команда разрастается или проекты увеличиваются этот подход создаст больше пробле проблем чем пользы. В итоге одни и теже сырцы будут разнесены, скопированы, продублированы.
Не хорошо..
Вариант второй: утилитные классы в отдельной папке, которую мы просто закидываем в наш солюшин, но уже в отдельный проект.
Почти тоже самое, что случай 1, но более цивилизованно. Уменьшается время сборки для тестового запуска
Третий: несколько проэктных файлов под каждый фрэймворк рядышком использующих один и тот же набор исходников
Вот это уже совсем по взрослому. Взрослый минус: при изменении файлов в проекте необходимо во всех проэктных файлах лежащих рядом добавить или удалить файлы. Мы программисты любим повторяться? Не-а. Но по всем остальным подходам - это очень правильно и цивилизованно, что избавляет от огромного числа потенциальных будущих проблем (если мы конечно не работаем по принципу: написали, отдали заказчику, забыли)
Четвертый: билд конфигурации определяющие какой фрэймворк и профайл будет использован для сборки
Один проект, все в одном месте. Даже удобнее, чем третий вариант. В чем подвох? Средствами студии создать такое нельзя. Дожились! 11 лет фрэймворку.
Открываем файл проекта в блокноте и в секции: <PropertyGroup> (та, что для всех) убираем теги: <TargetFrameworkVersion> и таргет схема.
Далее в каждой проперти группе <PropertyGroup Condition=...> добавляем эти теги сконфигурировав уже как нужно:
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'ReleaseFW3|AnyCPU'">
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;FW3</DefineConstants>
Теперь нужно сделать правильный референс к проектам:
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Runtime.Caching">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="System.Web" />
<Reference Include="System.Xml" />
</ItemGroup>
Этот код ставит зависимость на System.Runtime.Caching сборку, только если проект компилируется под .NET4
Правильно: "купание в море повышает настроение" (с) МЕГА. Айда купаться!
1 коментар:
http://msdn.microsoft.com/ru-ru/library/bb126445.aspx
Дописати коментар