在一个项目中编译Silverlight和WPF的最佳实践是什么?

12

我刚完成了一个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。在这两个文件夹旁边,我有一个“共享”文件夹,其中包含两个项目都使用的文件。到目前为止,它运行良好 :)

3个回答

10

更新:这证明了几乎总会有更简单的方法。 :-)

第一步是使用条件编译来隔离Silverlight特定的代码。(我假设你的“默认”目标是WPF。)

其次,您需要一个生成脚本,将为每个平台编译代码,并设置适当的定义和程序集引用。

看看开源Caliburn项目。它可以完成所有这些操作。

这里是来自Caliburn的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);
        }

如果您在VS中打开Caliburn并编译它,则会针对标准框架进行编译。引用是针对.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,则可能需要编辑NAnt.exe.config以匹配正确版本的Silverlight框架。对于Silverlight RTW,框架版本将是2.0.31005.0。


我认为Caliburn项目的正确链接现在是:http://www.codeplex.com/caliburn - bperreault

6
我自己没有尝试过(仍在寻找时间玩银光),但你不能有一个解决方案,其中包括两个项目,一个面向银光,一个面向.NET 3.5,并将公共类文件添加为链接到每个项目中(右键单击项目,添加现有项目...,添加为链接)吗?**更新:请参见马克下面的答案,有关项目连接器。我一直在使用这个PRISM 2.0 CAL多目标组合应用程序,并且它美妙绝伦。我认为这在PRISM 1.0中不存在?

3
你应该查看“模式和实践:组合WPF和Silverlight”。

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

它可以在同一解决方案中快速启动WPF / Silvelight版本的应用程序。还有一个“项目链接器”,当您更改Silverlight代码(或反之亦然)时会更新WPF应用程序的源代码,使用链接。当您具有特定于版本的代码时,可以覆盖它。示例仍然有点粗糙,但可能会让您了解如何处理您的项目。希望对您有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接