Как лучше всего компилировать Silverlight и WPF в одном проекте?

StackOverflow https://stackoverflow.com/questions/208123

Вопрос

Я только что завершил проект Silverlight, и пришло время немного подвести итоги.Я хотел бы взять свои основные файлы и поместить их в отдельный проект, на который я буду ссылаться из своего основного приложения Silverlight.Некоторые из этих классов совместимы с WPF, и мне бы очень хотелось иметь возможность использовать код Silverlight/WPF в одном проекте.Моим идеальным решением был бы один проект, допускающий несколько конфигураций.Так,

Конфигурация:Silverlight будет генерировать:Company.Controls.Silverlight.dll

Конфигурация:WPF сгенерирует:Company.Controls.Wpf.dll

Возможно ли иметь один и тот же источник в одном файле, только разделенном с помощью определений?

Кто-нибудь делал это раньше?

Редактировать: Я создал решение для каждого проекта, например MyCompany.Windows.Controls, которое затем содержит два проекта: MyCompany.Windows.Controls и MyCompany.Windows.Controls.Silverlight.Помимо этих двух папок у меня есть папка «Общая», содержащая файлы, используемые обоими проектами.Пока работает хорошо :)

Это было полезно?

Решение

Я сам не пробовал (все еще пытаюсь найти время поиграться с Silverlight), но не могли бы вы иметь одно решение с двумя проектами, один из которых ориентирован на Silverlight, а другой - на .NET 3.5, и добавить файлы общих классов в каждый проект как ссылку (щелкните проект правой кнопкой мыши, выберите «Добавить существующий элемент...», «Добавить как ссылку»)?

** Обновлять:См. ответ Марка ниже относительно Project Linker.Я использовал это в своем многоцелевом составном приложении с PRISM 2.0 CAL, и это прекрасная вещь.Я не думаю, что этого существовало в PRISM 1.0?

Другие советы

Обновлять:показывает, что почти всегда есть более простой путь.:-)

Первым шагом является использование условной компиляции для разделения кода 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) у вас будет цель, которая устанавливает определения для каждой платформы, например, цель Caliburn Silverlight:

<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.

Вам следует ознакомиться с «шаблонами и практиками:Композитный WPF и Silverlight"

http://www.codeplex.com/CompositeWPF/Wiki/View.aspx?title=Home

Он позволяет быстро начать работу с версиями WPF/Silvelight одного и того же приложения в одном решении.Также «Компоновщик проектов», который обновляет исходный код вашего приложения WPF при изменении кода Silverlight (или наоборот) с помощью связывания.Его можно переопределить, если у вас есть код конкретной версии.

Примеры все еще немного грубоваты, но они могут дать вам представление о том, как реализовать свой проект.

ХТХ

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top