2012-11-21

Using Assembly Attributes in .NET

This is a small excerpt from my book, The Reddick C# Style Guide: Best practices for writing C# code.
 
The AssemblyInfo.cs file contains attributes that describe the assembly. These are placed into the metadata for the assembly that is read by Windows and install programs. Microsoft has been casual about describing what should go into each of these attribute, and inconsistent on their use in their own assemblies. This section gives a consistent treatment on what should go into each one.
For the examples in this section, assume that there are two programs that Acme ships: Acme Financial Analysis and Acme Portfolio Optimizer. Both programs use the Acme Business Library, but only Acme Portfolio Optimizer uses the Acme Stock Retriever Library and the library is only ever used by the optimizer.
Acme.FinancialAnalysis.exe references
            Acme.BusinessLibrary.dll
Acme.PortfolioOptimizer.exe references
            Acme.BusinessLibrary.dll
            Acme.StockRetrieverLibrary.dll

AssemblyCompany: The AssemblyCompany attribute must have the company or organization that developed the assembly's legal name.

This Application.UserAppDataPath and Application.UserAppDataRegistry properties use the company name in the directory and registry keys where information is found.

[assembly: AssemblyCompany("Acme Corporation")]

AssemblyConfiguration: The AssemblyConfiguration attribute must have the configuration that was used to build the assembly.

Use conditional compilation to properly include different assembly configurations.
Use the block similar to the example below. Add as many different configurations as you commonly use.

#if (DEBUG)

[assembly: AssemblyConfiguration("Debug")]

#else

[assembly: AssemblyConfiguration("Release")]

#endif

AssemblyCopyright: The AssemblyCopyright attribute must have the copyright notice for the assembly.

The suggested form is "Copyright © 2020 Acme Corporation", however, consult with legal representation for the exact form that should be used in the country of publication. A (c) is not a substitution for a © symbol.

[assembly: AssemblyCopyright("Copyright © 2020 Acme
Corporation")]
All assemblies should have a copyright notice. Even open-source assemblies should have a copyright notice, but should be released under a liberal license agreement.
(See Circular 3: Copyright Notice from the U.S. Copyright Office for information about copyright notices in the United States, http://www.copyright.gov/circs/circ03.pdf.)

AssemblyCulture: The AssemblyCulture attribute must contain the culture that the assembly was built for.

The invariant culture that is used by default is indicated by a zero length string. Other cultures are indicated by the RFC 1766 (http://www.ietf.org/rfc/rfc1766.txt) description of the language and possibly country. Non-invariant cultures are used in satellite assemblies for internationalizing resources.

[assembly: AssemblyCulture("")]

[assembly: AssemblyCulture("es-SP")]

AssemblyDefaultAlias: The AssemblyDefaultAlias attribute may contain a friendly name for the assembly.

The AssemblyDefaultAlias provides an alternate friendly name for the assembly when the  assembly name file name is something unfriendly, such as a randomly generated name. Since a randomly generated name wouldn't follow the best practice for assembly names, it would be highly unusual to need an AssemblyDefaultAlias attribute, and it is infrequently used.

[assembly: AssemblyDefaultAlias("Generated Assembly")]

AssemblyDelaySign: The AssemblyDelaySign attribute must contain a boolean indicating whether to delay sign the assembly.

If delay signing is needed, set the value to true, otherwise set it to false. Delayed signing is used when the author of the assembly does not have access to the private key that will be used to eventually sign the assembly.

[assembly: AssemblyDelaySign(true)]

[assembly: AssemblyDelaySign(false)]

AssemblyDescription: The AssemblyDescription attribute must contain a short description of the purpose of this assembly.

This attribute provides a description of the purpose of this library. This should be a one-sentence or sentence fragment description, ending in a period.

The Acme.FinancialAnalysis project has this attribute

[assembly: AssemblyDescription("The Financial Analysis executable.")]

The Acme.PortfolioAnalyzer project has this attribute

[assembly: AssemblyDescription("The Portfolio Analyzer executable.")]

The Acme.StockRetrieverLibrary project has this attribute

[assembly: AssemblyDescription("Retrieves stock information from a web
service.")]

The Acme.BusinessLibrary project has this attribute

[assembly: AssemblyDescription("A set of common business functions.")]

AssemblyFileVersion: The AssemblyFileVersion attribute may be set to the version number of the specific file of the assembly.

The AssemblyFileVersion attribute is used as the version number of the specific file, as opposed to the assembly. This version number is used as the Win32 file version in the assembly, which is shown in the Windows interface, as well as used by some program that read that value. This number cannot contain a wildcard to generate build and revision numbers, unlike the AssemblyVersion attribute.
If this attribute is not present, then the AssemblyVersion attribute is also used for the AssemblyFileVersion. Using the AssemblyVersion for the file version is usually correct, so in most cases this attribute should not be present.

[assembly: AssemblyFileVersion("1.0.0.0")]

AssemblyInformationalVersion: The AssemblyInformationalVersion attribute should be set to the major and minor version number of the product.

The Application.UserAppDataPath or Application.UserAppDataRegistry properties reference paths and registry keys by building a string from the CompanyName, ProductName, and Version number. If this attribute is not present, then the value in AssemblyVersion attribute is used instead. If the wildcard is used in the AssemblyVersion attribute, the compiler will change the build and revision number on each build causing information stored on the disk and registry to be stored in a different directory or registry key.
The AssemblyInformationalVersion attribute is used to provide a consistent version number for this version of the product. It should be changed along with the AssemblyVersion attribute number when the major or minor version is changed.

[assembly: AssemblyInformationalVersion("3.0")]

[assembly: AssemblyVersion("3.0.*")]
Under some rare circumstances, this might be set to some other value than a pure version number. For example, suppose that there was a special build for a particular customer that should use separate registry keys or file paths. In such cases, it can be set to an arbitrary string. However, it will cause a FXCop warning that can be suppressed. In such a case it might be set like this:

[assembly: AssemblyInformationalVersion("3.0 CustomerX Build")]

AssemblyProduct: The AssemblyProduct attribute must contain the product name of the product that this assembly is a part of.

The product is the deliverable to the customer. Acme Financial Analysis is a product, so is Acme Portfolio Analyzer.

The Acme.FinancialAnalysis project has this attribute

[assembly: AssemblyProduct("Acme Financial Analysis")]

The Acme.PortfolioAnalyzer project has this attribute

[assembly: AssemblyProduct("Acme Portfolio Analyzer")]
The Acme Stock Retriever Library is only used with the Portfolio Analyzer. So the product for the Stock Retriever is the Portfolio Analyzer.

The Acme.StockRetrieverLibrary project has this attribute

[assembly: AssemblyProduct("Acme Portfolio Analyzer")]
The Acme Business Library, however is used by multiple projects. In this case, the product is the library itself, since that is what is delivered to the libraries that use it.

The Acme.BusinessLibrary project has this attribute

[assembly: AssemblyProduct("Acme Business Library")]

AssemblyTitle: The AssemblyTitle attribute must contain the friendly name for this assembly.

The AssemblyTitle is the friendly name of this particular assembly. A friendly name can contain spaces and other punctuation.

The Acme.FinancialAnalysis project has this attribute

[assembly: AssemblyTitle("Acme Financial Analysis UI")]

The Acme.PortfolioAnalyzer project has this attribute

[assembly: AssemblyTitle("Acme Portfolio Analyzer UI")]

The Acme.StockRetrieverLibrary project has this attribute

[assembly: AssemblyTitle("Acme Stock Retriever Library")]

The Acme.BusinessLibrary project has this attribute

[assembly: AssemblyTitle("Acme Business Library")]

AssemblyTrademark: The AssemblyTrademark attribute should be included if any trademarks or service marks are used in the assembly.

Trademarks should be stated in complete sentences with a period at the end. Consult with legal representation for the exact wording of such statements.

[assembly: AssemblyTrademark("Acme is a trademark of Acme
Corporation.")]

AssemblyVersion: The AssemblyVersion attribute must contain a valid version number for the assembly.

Applications run only with versions of an assembly for which they were built, by default. It is important to have the version marked.
The version number is constructed from four values:
  • Major Version
  • Minor Version
  • Build Number
  • Revision
The major and minor version number must be set to the number of the project you are building for. For initial releases, this should be set to 1.0. Major and minor releases should increment these numbers by one. When the major version is incremented, the minor version should be reset to zero. For any given release of the product, these numbers should remain constant.
The build and revision numbers are numbers that change for each build, alpha, or beta release. These change with every build of the assembly. The build and release numbers should be specified as an asterisk, which lets the compiler maintain them.
The default build number will increment daily. The default revision number is generated from the system clock, so should be larger on each build. There may be pathological cases where a new build has a lower build and revision number than a previous build, however, such as two separate builds on different machines where one clock is not set correctly.

[assembly: AssemblyVersion("3.0.*")]

X [assembly: AssemblyVersion("0.9.*")]

X [assembly: AssemblyVersion("1.1.3.27")]
When the major or minor version number are changed, the AssemblyInformationalVersion attribute should also be changed.
FxCop CA1016

CLSCompliant: The CLSCompliant attribute must be present and indicate the CLS compliance of the assembly.


[assembly: CLSCompliant(true)]

[assembly: CLSCompliant(false)]
FxCop CA1014

ComVisible: The ComVisible attribute must be present and indicate the default visability to COM.


[assembly: ComVisible(true)]

[assembly: ComVisible(false)]
FxCop CA1017

ContractVerification: The ContractVerification attribute must contain a boolean indicating the default static contract verification.

The value passed to the ContractVerification attribute becomes the default state for static analysis of the assembly. If the value passed is true, then static analysis is performed on the whole assembly, except where overidden. If the value passed is false, then no static analysis is performed, unless specifically overridden on a given class or member.
In most cases the value should be set to true. However if contracts are being added to an existing assembly there may be hundreds of warnings. In such case, the default might be set to false, and then turned on for a specific class or method to limit the number of warnings to a manageable level.

[assembly: ContractVerification(true)]

[assembly: ContractVerification(false)]

Guid: The Guid attribute must be present and assigned to a unique value.

The Guid attribute uniquely identifies this assembly to COM. The value must not be copied from any other assembly; it should be generated by a Guid generator. A Guid generator can be found on the Tool menu in Visual Studio.

[assembly: Guid("518dfb74-78ea-46dd-a4ac-3bda80e47290")]

InternalsVisibleTo: The InternalsVisibleTo attribute may be included to expose internal variables to other libraries.

This attribute allows access to the internals of an assembly to another assembly, The most common use of this attribute is to expose the internals of this assembly to a unit test assembly. If the assembly is properly signed with a strong name, then the PublicKey property needs to be the public key of the strong name of the assembly specified.

[assembly: InternalsVisibleTo("Acme.BusinessLibrary.Tests,
PublicKey="0023000004800000...309450b2")]

NeutralResourcesLanguages: The NeutralResourcesLanguages in a main assembly must be set to the language of the resources contained within it.

If a main assembly contains resources, the NeutralResourcesLanguageAttribute tells .NET that the neutral resources are also the resources for that language. This makes it clear to .NET that it does not need to look for a satellite assembly for that language. In most cases, this will be the codes for the language and country of the programming team. This value is set to the RFC 1766 (http://www.ietf.org/rfc/rfc1766.txt) specifier of the language and country.
Even if the assembly doesn't have resources, the attribute indicates the language that the developer's used.

[assembly: NeutralResourcesLanguageAttribute("en-US")]

No comments :

Post a Comment

Note: Only a member of this blog may post a comment.