Какова наилучшая практика для компиляции Silverlight и WPF в одном проекте? - PullRequest
12 голосов
/ 16 октября 2008

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

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

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

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

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

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

Ответы [ 3 ]

10 голосов
/ 17 октября 2008

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

Первым шагом является использование условной компиляции для разделения кода Silverlight. (Я предполагаю, что ваша цель по умолчанию - WPF.)

Во-вторых, вам понадобится скрипт сборки, который скомпилирует код для каждой платформы, установив соответствующие определения и ссылки на сборки.

Взгляните на открытый исходный код Caliburn project . Это делает все это.

Вот пример из класса ExtensionMethods Калибурна.

    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.

6 голосов
/ 17 октября 2008

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

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

3 голосов
/ 13 ноября 2008

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

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

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

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

НТН

...