Quais são as melhores práticas para usar Atributos de Montagem?

163

Eu tenho uma solução com vários projetos. Eu estou tentando otimizar arquivos AssemblyInfo.cs vinculando um arquivo de informações de assembly amplo da solução. Quais são as melhores práticas para fazer isso? Quais atributos devem estar no arquivo amplo da solução e quais são específicos do projeto / montagem?


Edit: Se você estiver interessado, há uma pergunta de acompanhamento Quais são as diferenças entre AssemblyVersion, AssemblyFileVersion e AssemblyInformationalVersion?

Jakub Šturc
fonte

Respostas:

207

Estamos usando um arquivo global chamado GlobalAssemblyInfo.cs e um local chamado AssemblyInfo.cs. O arquivo global contém os seguintes atributos:

 [assembly: AssemblyProduct("Your Product Name")]

 [assembly: AssemblyCompany("Your Company")]
 [assembly: AssemblyCopyright("Copyright © 2008 ...")]
 [assembly: AssemblyTrademark("Your Trademark - if applicable")]

 #if DEBUG
 [assembly: AssemblyConfiguration("Debug")]
 #else
 [assembly: AssemblyConfiguration("Release")]
 #endif

 [assembly: AssemblyVersion("This is set by build process")]
 [assembly: AssemblyFileVersion("This is set by build process")]

O AssemblyInfo.cs local contém os seguintes atributos:

 [assembly: AssemblyTitle("Your assembly title")]
 [assembly: AssemblyDescription("Your assembly description")]
 [assembly: AssemblyCulture("The culture - if not neutral")]

 [assembly: ComVisible(true/false)]

 // unique id per assembly
 [assembly: Guid("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")]

Você pode adicionar o GlobalAssemblyInfo.cs usando o seguinte procedimento:

  • Selecione Adicionar / item existente ... no menu de contexto do projeto
  • Selecione GlobalAssemblyInfo.cs
  • Expanda o botão Adicionar clicando na pequena seta para baixo à direita
  • Selecione "Adicionar como link" na lista suspensa de botões
JRoppert
fonte
qual é o objetivo de manter os antigos arquivos AssemblyInfo.cs por aí? Quando automatizo meu carimbo de versão de compilação no GlobalAssemblyInfo.cs, como isso atualiza os arquivos AssemblyInfo.cs que tenho em minha solução?
D3vtr0n
3
@Devtron Os arquivos AssemblyInfo individuais devem fornecer informações exclusivas da montagem em que residem (por exemplo, título, descrição e cultura, como no exemplo acima). Entradas comuns, como o nome do produto e as informações de versão, devem ser removidas (e causarão um erro no compilador se forem duplicadas). Idealmente, os arquivos AssemblyInfo não serão atualizados pelo processo de compilação.
David Keaveny
1
O AssemblyCultureAttributemerece uma explicação melhor. O atributo deve estar ausente completamente (a menos que seja um assembly satélite). Ao usar montagens satélites em larga escala, pode ser necessário três, e não dois níveis de arquivos de informações de montagem (global, montagem principal e montagem de satélite, que especificam apenas a cultura nesse caso).
Jirka Hanika
20

No meu caso, estamos construindo um produto para o qual temos uma solução do Visual Studio, com vários componentes em seus próprios projetos. Os atributos comuns vão. Na solução, existem cerca de 35 projetos e uma informação de montagem comum (CommonAssemblyInfo.cs), que possui os seguintes atributos:

[assembly: AssemblyCompany("Company")]
[assembly: AssemblyProduct("Product Name")]
[assembly: AssemblyCopyright("Copyright © 2007 Company")]
[assembly: AssemblyTrademark("Company")]

//This shows up as Product Version in Windows Explorer
//We make this the same for all files in a particular product version. And increment it globally for all projects.
//We then use this as the Product Version in installers as well (for example built using Wix).
[assembly: AssemblyInformationalVersion("0.9.2.0")]

Os outros atributos, como AssemblyTitle, AssemblyVersion, etc., são fornecidos por montagem. Ao criar uma montagem, AssemblyInfo.cs e CommonAssemblyInfo.cs são criados em cada montagem. Isso nos dá o melhor dos dois mundos, onde você pode querer ter alguns atributos comuns para todos os projetos e valores específicos para outros.

Espero que ajude.

Krishna
fonte
você tem mais de 35 entradas em sua configuração de compilação para lidar com isso? Parece bastante redundante. E se você adicionar 2 ou 3 novos projetos, isso interromperá a construção até você adicioná-los à tarefa de controle de versão?
D3vtr0n
1
@ D3vtr0n, por que uma “configuração de compilação” (o que você quer dizer com isso) precisa de tantas entradas? Presumo que esse arquivo esteja incluído em cada arquivo .csproj <Compile Include="$(MSBuildThisFileDirectory)..\Common\CommonAssemblyInfo.cs"/>, uma diretiva MSBuild que pode até estar em um Common.targetsarquivo compartilhado . Reutilização de código yay.
binki
15

A solução apresentada por @JRoppert é quase a mesma que eu faço. A única diferença é que eu coloquei as seguintes linhas no arquivo AssemblyInfo.cs local, pois elas podem variar com cada montagem:

#if DEBUG
[assembly: AssemblyConfiguration("Debug")]
#else
[assembly: AssemblyConfiguration("Release")]
#endif
[assembly: AssemblyVersion("This is set by build process")]
[assembly: AssemblyFileVersion("This is set by build process")]
[assembly: CLSCompliant(true)]

Eu também (geralmente) uso uma informação de montagem comum por solução, com a suposição de que uma solução é uma única linha de produto / produto liberável. O arquivo de informações de montagem comum também possui:

[assembly: AssemblyInformationalVersion("0.9.2.0")]

O que definirá o valor "ProductVersion" exibido pelo Windows Explorer.

Scott Dorman
fonte
8

As Tarefas da Comunidade MSBuild contêm uma tarefa personalizada chamada AssemblyInfo que você pode usar para gerar seu assemblyinfo.cs. Requer uma pequena edição manual dos arquivos csproj para usar, mas vale a pena.

jlew
fonte
6

Na minha opinião, usar um GlobalAssemblyInfo.cs é mais problemático do que vale a pena, porque você precisa modificar todos os arquivos de projeto e lembre-se de modificar cada novo projeto, enquanto você obtém um AssemblyInfo.cs por padrão.

Para alterações nos valores globais (por exemplo, empresa, produto etc.), as alterações geralmente são tão raras e simples de gerenciar que não considero o DRY uma consideração. Basta executar o seguinte script MSBuild (dependente do MSBuild Extension Pack ) quando desejar alterar manualmente os valores em todos os projetos como um caso único:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="UpdateAssemblyInfo" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

    <ItemGroup>
        <AllAssemblyInfoFiles Include="..\**\AssemblyInfo.cs" />
    </ItemGroup>

    <Import Project="MSBuild.ExtensionPack.tasks" />

  <Target Name="UpdateAssemblyInfo">
    <Message Text="%(AllAssemblyInfoFiles.FullPath)" />
    <MSBuild.ExtensionPack.Framework.AssemblyInfo 
        AssemblyInfoFiles="@(AllAssemblyInfoFiles)"
        AssemblyCompany="Company"
        AssemblyProduct="Product"
        AssemblyCopyright="Copyright"
        ... etc ...
        />
  </Target>

</Project>
Jack Ukleja
fonte
3

Para compartilhar um arquivo entre vários projetos, você pode adicionar um arquivo existente como um link.

Para fazer isso, adicione um arquivo existente e clique em "Adicionar como link" no seletor de arquivos. (fonte: free.fr )Adicionar como link

Quanto ao que colocar no arquivo compartilhado, sugiro colocar coisas que seriam compartilhadas entre assemblies. Coisas como direitos autorais, empresa, talvez versão.

Cameron MacFarland
fonte
1

O uso de um único arquivo AseemblyInfo.cs para vários projetos não é recomendado. O arquivo AssemblyInfo inclui informações que podem ser relevantes apenas para esse assembly específico. As duas informações mais óbvias são: AssemblyTitlee AssemblyVersion.

Uma solução melhor pode ser usar o targetsarquivo manipulado pelo MSBuild para "injetar" atributos de montagem em mais de um projeto.

SaguiItay
fonte
e se você tiver mais de 20 projetos? Isso exige que eu mantenha mais de 20 entradas na minha configuração de compilação, apenas para controle de versão. Isso parece realmente manco. E se eu adicionar 2 ou 3 novos projetos? Isso definitivamente interromperá o processo de compilação ... Alguma idéia de como solucionar isso?
D3vtr0n
@ D3vtr0n Acho que a ideia é gerar dinamicamente o Assembly relevante e não manter configurações individuais para cada projeto. As Tarefas da Comunidade, eu acho, lida com esse caso.
Roman
1

Uma coisa que achei útil é gerar os elementos AssemblyVersion (etc) aplicando a substituição de token na fase de pré-construção.

Eu uso o TortoiseSVN, e é fácil de usar a sua SubWCRev.exepara transformar um modelo AssemblyInfo.wcrevem AssemblyInfo.cs. A linha relevante no modelo pode ser algo como isto:

[assembly: AssemblyVersion("2.3.$WCREV$.$WCMODS?1:0$$WCUNVER?1:0$")]

O terceiro elemento é o número da revisão. Uso o quarto elemento para verificar se não esqueci de confirmar nenhum arquivo novo ou alterado (o quarto elemento é 00 se estiver tudo OK).

A propósito, adicione AssemblyInfo.wcrev ao seu controle de versão e ignore AssemblyInfo.cs se você usar isso.

John Denniston
fonte