Qual é a melhor prática para compilar Silverlight e WPF em um projeto?
-
03-07-2019 - |
Pergunta
I acabou de completar um projeto do Silverlight e é hora de ter um pouco de limpeza. Eu gostaria de ter meus arquivos principais e colocá-los em um projeto separado que I fará referência do meu principal aplicativo Silverlight. Algumas destas classes são compatíveis com WPF e eu gostaria muito de ser capaz de ter código Silverlight / WPF tudo em um projeto. Minha solução ideal seria um projeto único que permite várias configurações. Então,
Configuração: Silverlight geraria: Company.Controls.Silverlight.dll
Configuração: WPF geraria: Company.Controls.Wpf.dll
É possível ter a mesma origem no mesmo arquivo apenas separados via define?
Alguém já fez isso antes?
Editar: Eu criei uma solução por projeto, como MyCompany.Windows.Controls, que então contém 2 projectos, MyCompany.Windows.Controls & MyCompany.Windows.Controls.Silverlight. Juntamente com essas 2 pastas Eu tenho uma pasta "Shared", que contém arquivos usados ??por ambos os projectos. Ele funciona bem até agora:)
Solução
Eu não tentei me (ainda tentando encontrar o tempo para brincar com Silverlight), mas você não poderia ter uma solução com dois projetos, um targetting Silverlight ea outra segmentação .NET 3.5, e adicionar o comum arquivos de classe para cada projeto como links (clique com o botão direito no projeto, Adicionar item existente ... Adicionar como link)?
** Update: resposta See de Mark abaixo sobre o Linker Projeto. Eu tenho usado isso no meu aplicativo multi-alvejado composta com o PRISM 2.0 CAL e é uma coisa linda. Eu não acho que isso existia na PRISM 1.0?
Outras dicas
Atualização: vai mostrar que há quase sempre uma maneira mais fácil. : -)
O primeiro passo é usar compilação condicional para segregar o código específico Silverlight. (Estou assumindo que o seu "default" alvo com seja WPF).
Em segundo lugar, você precisará de um script de construção que irá compilar o código para cada plataforma, definindo as define apropriadas e montagem referências.
Dê uma olhada no código-fonte aberto Caliburn projeto . Ele faz tudo isso.
Aqui está um exemplo da classe ExtensionMethods de 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);
}
Se você abrir Caliburn no VS e compilá-lo, cumpre contra a estrutura padrão. As referências são para NET 3.5 e WPF, não Silverlight. Isso também é por isso que as directivas de pré-processamento são "! SILVERLIGHT".
No seu script de construção (Caliburn usa NAnt), você vai ter um alvo que define o define para cada plataforma, por exemplo, alvo Silverlight da 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>
Então aqui é o alvo que invocam a construção Silverlight real:
<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>
Finalmente, aqui está um exemplo do alvo "core", que é responsável pela produção do 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>
Observe a forma como é referenciando as montagens necessárias.
Você provavelmente precisará editar o seu NAnt.exe.config (se você estiver usando NAnt) para coincidir com a versão correta do quadro Silverlight. Para Silverlight RTW, a versão do framework será 2.0.31005.0.
Você deve verificar se "padrões e práticas: Composite WPF e Silverlight"
http://www.codeplex.com/CompositeWPF/Wiki /View.aspx?title=Home
Tem partidas rápidas com versões WPF / Silvelight do mesmo aplicativo em uma única solução. Também um "Projeto Linker" que atualiza a fonte de seu aplicativo WPF quando você alterar o código do Silverlight (ou vice-versa) utilizando a ligação. Ele pode ser substituído quando você tem o código versão específica.
Os exemplos são ainda um pouco áspero em torno das bordas, mas pode dar-lhe uma idéia de como ir sobre seu projeto.
HTH