What is the best practice for compiling Silverlight and WPF in one project?

和自甴很熟 提交于 2020-01-10 10:24:19

问题


I've just completed a Silverlight project and it's time to have a little clean up. I'd like to take my core files and put them into a separate project which I will reference from my main Silverlight app. Some of these classes are compatible with WPF and I would quite like to be able to have Silverlight / WPF code all in one project. My ideal solution would be a single project that allows multiple configurations. So,

Configuration: Silverlight would generate: Company.Controls.Silverlight.dll

Configuration: WPF would generate: Company.Controls.Wpf.dll

Is it possible to have the same source in the same file just seperated via defines?

Has anyone done this before?

Edit: I've created a solution per project, like MyCompany.Windows.Controls, which then contains 2 projects, MyCompany.Windows.Controls & MyCompany.Windows.Controls.Silverlight. Alongside those 2 folders I have a "Shared" folder, which contains files used by both projects. It works well so far :)


回答1:


I haven't tried it myself (still trying to find the time to play with Silverlight), but couldn't you have one solution with two projects, one targetting Silverlight and the other targetting .NET 3.5, and add the common class files to each project as Links (right-click the project, Add Existing Item..., Add as Link)?

** Update: See Mark's answer below regarding the Project Linker. I've been using this in my multi-targetted composite application with the PRISM 2.0 CAL and it's a beautiful thing. I don't think this existed in PRISM 1.0?




回答2:


Update: goes to show that there is almost always an easier way. :-)

The first step is to use conditional compilation to segregate the Silverlight specific code. (I'm assuming that your "default" target with be WPF.)

Secondly, you'll need a build script that will compile the code for each platform, setting the appropriate defines and assembly references.

Take a look at the open-source Caliburn project. It does all this.

Here's an example from Caliburn's ExtensionMethods class.

    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);
        }

If you open Caliburn in VS and compile it, it complies against the standard framework. The references are for .NET 3.5 and WPF, not Silverlight. That is also why the pre-processing directives are "!SILVERLIGHT".

In your build script (Caliburn uses NAnt), you'll have a target that sets the defines for each platform, for example, Caliburn's Silverlight target is:

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

Then here is the target that invoke the actual Silverlight build:

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

Finally, here is an example of the "core" target that is responsible for producing the 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>

Notice the way it's referencing the necessary assemblies.

You'll probably need to edit your NAnt.exe.config (if you are using NAnt) to match the correct version of the Silverlight framework. For Silverlight RTW, the framework version will be 2.0.31005.0.




回答3:


You should check out "patterns & practices: Composite WPF and Silverlight"

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

It has quick starts with WPF/Silvelight versions of the same app in one solution. Also a "Project Linker" that updates the source of your WPF app when you change Silverlight code (or vice versa) using linking. It can be overridden when you have version specific code.

The examples are still a little rough around the edges but it may give you an idea of how to go about your project.

HTH



来源:https://stackoverflow.com/questions/208123/what-is-the-best-practice-for-compiling-silverlight-and-wpf-in-one-project

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!