Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Satellite Assemblies


Satellite Assemblies

All code in .NET is packaged in assemblies; these are standard Windows PE (portable executable) files, either EXEs (processes) or DLLs (libraries). A version can be applied to a library assembly using the [AssemblyVersion] custom attribute. The compiler stores this version in the assembly that uses the library, and the run-time library loading technology, Fusion, uses the version specified with this attribute to load the correct (strong named) library assembly. Satellite assemblies are DLLs, but although the name may suggest that they are located and loaded in a similar way to library assemblies, they are actually loaded using a different mechanism. Further, there is a versioning attribute specifically for satellite assemblies, [SatelliteContractVersion], but this is applied to the assembly that uses the satellite rather than the satellite. So what are satellites, when should you use them, and what is this extra version attribute?

The first point to make is that satellite assemblies are used to hold resources (strings, icons, bitmaps, etc.) and generally do not have code. I say ‘generally’ because you are not prevented from having code in a satellite assembly; however, satellite assemblies are loaded at run time dynamically, and so at compile time the compiler is unaware of the types in the satellite and so it cannot perform type checking. This means that if you want to use the types in a satellite you have to use reflection to access them, which is not the most convenient way to call code.

There are two ways to create a satellite. The first way is to use your language compiler to create a library assembly with an embedded resource and to mention the culture of the assembly using the [AssemblyCulture] custom attribute. This requires that you have at least one code file, but that file does not have to define a type or an entrypoint. The other way is to use the assembly linker tool, al.exe, and specify the resource and culture on the command line; this does not require a code source file.

The name of the resource and the name of the satellite are important. The resource must be in the form:

<resource_name>.<culture>.resources

For example, mystrings.en-GB.resources, for the UK English version of the resource. The process that uses the satellite should contain the culture neutral version of the resource and this resource should be in the form:

<resource_name>.resources 

The satellite has to have a name based on the name of the assembly that will use it. If this assembly is called MyApp.exe, the satellite must be called MyApp.resources.dll. However, if you have multiple satellites, this will mean that they all have the same PE name. One solution would be to install these satellites into the GAC, because the GAC can hold multiple libraries that have the same short name but have different versions, cultures, or publisher. However, if you decide that the satellite should not be available to other processes, the satellite should be installed in the application folder or in a subfolder. To get around the Win32 file-naming problem, the .NET framework has created a convention where the satellites should be stored in folders that have the name of the culture. Thus, the application MyApp.exe will have subfolders with the names of the cultures that are supported (for example, en-GB for UK English satellites and fr-CA for French Canadian satellites) and each of these folders will have a library assembly called MyApp.resources.dll.

At run time, the process has the responsibility to load the correct satellite. The process does this through the ResourceManager class. There are several constructors, but the one you are most likely to use takes the name of the resource (in this example, this will be mystrings) and a reference to the assembly that contains the neutral resource. When you request a resource, this class will look at the UI culture set on the current thread (through CultureInfo.CurrentUICulture) and will load the appropriate satellite and access the specified resource. Since the UI culture can only be known at run time, you cannot indicate to the compiler at compile time which library will be used. Thus, if you reference a type defined in the satellite, the compiler will not be able to perform type checks and will issue an error. Note that if you set a Language property on a form in the Forms designer in Visual Studio .NET, the designer will add this code to your form class.

Another affect of the ResourceManager class loading satellites dynamically is that it needs to have some idea of the version of the satellite to use. Normally, the compiler is told the code libraries that an assembly will use and the compiler reads the version of those code libraries and places this version in the manifest of the assembly it is building. This way, the same library will be loaded at run time because the run time will read the manifest of the assembly to get a list of the libraries it uses and passes this onto Fusion to find the exact library specified.

Satellites can be versioned, but it is the developer that has the responsibility of telling the run time which version should be used. This is done through the [SatelliteContractVersion] attribute. When the ResourceManager class loads a satellite, it reads the [SatelliteContractVersion] attribute from the assembly loading the satellite and ensures that the satellite has the same version. The contract version applies to all the satellites that it uses. If the calling assembly changes its version will change, but it can still use the same satellites by keeping the same contract version. During a rebuild of the application you can change the version of the satellites, but the change must be the same for all satellites and the contract version must be changed accordingly. If just one satellite changes (for example, for a service pack) then its version must be changed, and you have to provide redirection information in a publisher policy file so that the contract version is overridden for this single satellite.

So, in summary, satellite assemblies are used to provide culture-specific resources and the ResourceManager is used to load the appropriate resource based on either the UI Culture of the current thread or a culture that you explicitly specify. Satellites can be versioned and to indicate that an assembly should use a specific version of satellites, you can use the [SatelliteContractVersion] in the calling assembly.


Richard Grimes speaks at conferences and writes extensively on .NET, COM, and COM+. He is the author of Developing Applications with Visual Studio .NET (Addison-Wesley, 2002). If you have comments about this topic, Richard can be reached at [email protected].


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.