Я только что завершил проект Silverlight, и пришло время немного поправить. Я хотел бы взять свои основные файлы и поместить их в отдельный проект, на который я буду ссылаться в моем основном приложении Silverlight. Некоторые из этих классов совместимы с WPF, и я бы очень хотел иметь код Silverlight / WPF в одном проекте. Моим идеальным решением был бы один проект, допускающий несколько конфигураций. Так,
Конфигурация: Silverlight сгенерирует: Company.Controls.Silverlight.dll
Конфигурация: WPF сгенерирует: Company.Controls.Wpf.dll
Возможно ли, чтобы один и тот же источник в одном файле был разделен с помощью определений?
Кто-нибудь делал это раньше?
Редактировать: Я создал решение для каждого проекта, например MyCompany.Windows.Controls, которое затем содержит 2 проекта: MyCompany.Windows.Controls и MyCompany.Windows.Controls.Silverlight. Наряду с этими двумя папками у меня есть папка «Shared», которая содержит файлы, используемые обоими проектами. Пока работает хорошо :)





Обновление: показывает, что почти всегда есть более простой способ. :-)
Первый шаг - использовать условную компиляцию для разделения кода, специфичного для Silverlight. (Я предполагаю, что ваша цель "по умолчанию" - WPF.)
Во-вторых, вам понадобится сценарий сборки, который будет компилировать код для каждой платформы, задавая соответствующие определения и ссылки на сборки.
Взгляните на Калибурн проект с открытым исходным кодом. Он все это делает.
Вот пример из класса ExtensionMethods от Caliburn.
public static T GetResource<T>(this FrameworkElement element, object key)
{
DependencyObject currentElement = element;
while (currentElement != null)
{
var frameworkElement = currentElement as FrameworkElement;
if (frameworkElement != null && frameworkElement.Resources.Contains(key))
return (T)frameworkElement.Resources[key];
#if !SILVERLIGHT
currentElement = (LogicalTreeHelper.GetParent(currentElement) ??
VisualTreeHelper.GetParent(currentElement));
#else
currentElement = VisualTreeHelper.GetParent(currentElement);
#endif
}
if (Application.Current.Resources.Contains(key))
return (T)Application.Current.Resources[key];
return default(T);
}
Если вы откроете Caliburn в VS и скомпилируете его, он будет соответствовать стандартной структуре. Ссылки относятся к .NET 3.5 и WPF, а не к Silverlight. Вот почему директивы предварительной обработки - "! SILVERLIGHT".
В вашем сценарии сборки (Caliburn использует NAnt) у вас будет цель, которая устанавливает определения для каждой платформы, например, цель Silverlight Caliburn:
<target name = "config-platform-silverlight20">
<property name = "nant.settings.currentframework" value = "silverlight-2.0"/>
<property name = "build.platform" value = "silverlight-2.0"/>
<property name = "build.defines" value = "${global.build.defines},SILVERLIGHT,SILVERLIGHT_20,NO_WEB,NO_REMOTING,NO_CONVERT,NO_PARTIAL_TRUST,NO_EXCEPTION_SERIALIZATION,NO_SKIP_VISIBILITY,NO_DEBUG_SYMBOLS"/>
<property name = "current.path.bin" value = "${path.bin}/silverlight-2.0/${build.config}"/>
<property name = "current.path.test" value = "${path.bin}/silverlight-2.0/tests" />
<property name = "current.path.lib" value = "${path.lib}/Silverlight" />
</target>
Тогда вот цель, которая вызывает фактическую сборку Silverlight:
<target name = "platform-silverlight20" depends = "config">
<if test = "${framework::exists('silverlight-2.0')}">
<echo message = "Building Caliburn ${build.version} for Silverlight v2.0."/>
<call target = "config-platform-silverlight20"/>
<copy todir = "${current.path.bin}">
<fileset basedir = "${current.path.lib}">
<include name = "*.dll"/>
<include name = "*.xml"/>
</fileset>
</copy>
<call target = "core"/>
<call target = "messaging"/>
<call target = "actions"/>
<call target = "commands"/>
<call target = "package-platform"/>
</if>
<if test = "${not(framework::exists('silverlight-2.0'))}">
<echo message = "Silverlight v2.0 is not available. Skipping platform."/>
</if>
</target>
Наконец, вот пример «основной» цели, которая отвечает за создание Caliburn.Core.dll:
<target name = "core" depends = "config, ensure-platform-selected">
<mkdir dir = "${current.path.bin}"/>
<csc keyfile = "${path.src}/Caliburn.snk" noconfig = "true" warnaserror = "false" target = "library" debug = "${build.debug}" optimize = "${build.optimize}" define = "${build.defines}"
output = "${current.path.bin}/Caliburn.Core.dll"
doc = "${current.path.bin}/Caliburn.Core.xml">
<sources basedir = "${path.src}">
<include name = "${build.asminfo}"/>
<include name = "Caliburn.Core/**/*.cs"/>
</sources>
<references basedir = "${current.path.bin}">
<include name = "mscorlib.dll"/>
<include name = "System.dll"/>
<include name = "System.Core.dll"/>
<!--WPF-->
<include name = "PresentationCore.dll"/>
<include name = "PresentationFramework.dll"/>
<include name = "WindowsBase.dll"/>
<!--Silverlight-->
<include name = "System.Windows.dll" />
</references>
<nowarn>
<warning number = "1584"/>
</nowarn>
</csc>
</target>
Обратите внимание на то, как он ссылается на необходимые сборки.
Возможно, вам потребуется отредактировать файл NAnt.exe.config (если вы используете NAnt), чтобы он соответствовал правильной версии платформы Silverlight. Для Silverlight RTW версия фреймворка будет 2.0.31005.0.
Я сам не пробовал (все еще пытаюсь найти время поиграть с Silverlight), но не могли бы вы иметь одно решение с двумя проектами, один нацелен на Silverlight, а другой на .NET 3.5, и добавить общие файлы классов в каждый проект как ссылки (щелкните проект правой кнопкой мыши, «Добавить существующий элемент ...», «Добавить как ссылку»)?
** Обновление: см. Ответ Марка ниже относительно Project Linker. Я использовал это в своем многоцелевом составном приложении с PRISM 2.0 CAL, и это прекрасно. Я не думаю, что это существовало в PRISM 1.0?
Вам следует ознакомиться с «шаблонами и практиками: составной WPF и Silverlight».
http://www.codeplex.com/CompositeWPF/Wiki/View.aspx?title=Home
Он позволяет быстро начать работу с версиями одного и того же приложения WPF / Silvelight в одном решении. Также «Project Linker», который обновляет исходный код вашего приложения WPF, когда вы меняете код Silverlight (или наоборот) с помощью связывания. Его можно переопределить, если у вас есть код конкретной версии.
Примеры все еще немного грубоваты, но они могут дать вам представление о том, как вести свой проект.
HTH
Я думаю, что сейчас правильная ссылка для проекта Caliburn: codeplex.com/caliburn