1. Computing

The .NET Framework - Assemblies

The Fundamental Unit of Code in .NET

By

Updated November 25, 2011

One of the biggest changes in Microsoft .NET architecture is the concept of assemblies. Although the term assembly is new, the concepts that make it a good idea have been around for decades and they're a lot easier to understand than you might think. This article is an introduction to .NET assemblies and how you can make them work for you.

An assembly is the .NET name for an executable file. In other words, a .NET assembly is just the .EXE or .DLL file that is the end result of your program. There are two ways that all of the .NET Framework is organized so that the different parts of a system can work together efficiently.

About Visual Basic offers a whole series of articles about the .NET Framework and the tools used to work with it. An introduction to the series - which starts with a list of the articles available - can be found here: Framework Tools - About the Tools.

From a Microsoft article:

-> An assembly provides a fundamental unit of physical code grouping.
-> A namespace provides a fundamental unit of logical code grouping.

But what does it mean to say that an assembly is a "fundamental unit"? Here are some of the things that are controlled by .NET at the assembly level.

Security: Permissions are requested and granted for the assembly, but not individually for anything inside an assembly. In Microsoft's terminology, the assembly is the security boundary.

Type Definitions: A "type" is a particular kind of object. Integer is a type, but if you define an object in your project, it's a type too. So, since two programmers might easily create a type with the same name (such as "AccountNum"?), .NET has to be able to distinguish one from another. For this reason, every type's identity includes the name of the assembly that it's in and the naming of assemblies makes these types unique. Microsoft calls this a reference scope boundary.

Versioning and Deployment: The assembly is the smallest versionable unit in .NET and the version is in the manifest. It's also the smallest unit that can be deployed.

The internal organization of the .NET assembly is entirely new with .NET. A .NET executable is actually the source code of an IL (Intermediate Language) program - unless you have used NGEN to create a native code executable. (See the About Visual Basic article about using NGEN, Framework Tools - NGEN) When you execute a .NET assembly, you're really just invoking a .NET runtime - called the CLR, Common Language Runtime - to compile the assembly into native code just before it's executed. This is sometimes called the .NET Just-In-Time (JIT) compiler.

It's easy to look at the IL code in your program. Just use the ILDASM program, the IL Dis-Assembler as explained in the About Visual Basic article, Framework Tools - ILDASM.

There are lots of benefits that are built into the .NET architecture. For example, if your program is a component, you can "install" it by simply copying it to a new location. There is no need to register components in the Windows registry as was once necessary in VB6 using the COM architecture. And you no longer have to worry about "breaking" systems because a component was overwritten with an incompatible later version. In the COM architecture, this problem is called "DLL Hell". But .NET architecture can keep track of every component with a unique version number even when they have the same name. You can specify that a program should use a new version of a component or the old one that it was tested with.

Another benefit is that systems can be programmed using different languages with complete freedom. After they're compiled into an assembly, they're all just IL programs. Different programmers working on the same project can use different languages, as long as they're all .NET based. (Visual Studio doesn't support this directly, but .NET does.)

Side note: There are still some people who claim that Visual Basic is in some way inferior to other .NET languages. Any programmer who says that now is just demonstrating a lack of technical understanding. The only difference now is how much the language helps you write and debug your program. Visual Basic has always been easy to read and understand.

And still another benefit is that "resources" - such as a graphic file - can be embedded right in the assembly for ease of updating and deploying your system and adding security so the resource doesn't get altered or replaced with something else. Assemblies can even be created using several individual files if you have that requirement. For example, type metadata and resources can be in different files. But the CLR still manages the whole assembly as a single fundamental unit.

In the bad old days of COM, shared components were usually dumped into that unorganized Windows warehouse, the System directory, and then "registered" in Windows so other programs could find them. This is a big reason why the registry is such a critical and sensitive part of Windows. Without it, one piece of software can't locate another one. (The registry is still used in .NET. But .NET doesn't use it to identify components anymore.) In .NET, every assembly starts with something called a manifest that takes the place of the information that was formerly placed in the registry. The manifest contains metadata (data about data) telling the CLR what it needs to know to execute the assembly instructions.

One of the things the CLR needs to know is the version number of components used by the assembly so the correct one can be matched up with it. To illustrate the point, let's compare the manifest of a very simple .NET component (DLL file) using the ILDASM utility. Every program needs the CoreLib component, so the illustration shows that assemblies that specify different versions of Framework reference the correct version of CoreLib.

--------
Click Here to display the illustration
--------

Everything is verified by passing an encryption key token to prevent unauthorized changes. If you create a component of your own and reference it, exactly the same versioning and security will guarantee that the right component is used. This is why you can run several versions of .NET and also a COM based Visual Studio 6 side-by-side with never a problem. Each version uses only the components programmed and tested with it. You can run your own versions of identically named programs side-by-side just as easily.

VB.NET gets the information necessary for the assembly manifest from the AssemblyInfo.vb file in your project. To check out the contents of AssemblyInfo.vb, click the Show All Files button in Solution Explorer and then click View Code for AssemblyInfo.vb under your project. This is an XML file so if you can simply change it by editing it directly in Visual Studio or even with a separate text editor. Or you can change it in Visual Studio in the Assembly Information dialog under the Project > Properties menu selection. Click the Assembly Information button. This is also the information you see when you right-click an executable file under Windows and select properties. (But, see the Quick Tip on Versions of Your Programs about the version information there.)

Assemblies can also provide culture information so that types can be used the way the target culture for the assembly expects them to appear. But if an assembly does contain culture information, it's automatically assumed to be a satellite assembly. Since there can be several satellite assemblies, all with different culture information, the same base system can be localized for different cultures.

One reason that COM dumped everything into the Windows system directory was to make a single copy available to any program that needed it. This works for components that are used by a lot of different programs (unless you run into the problem of incompatible versions - DLL Hell - mentioned earlier). But even if no other program references a unique component developed for just one system, you have to go through the same registration when you use COM. A big improvement in .NET architecture is that it this registration just isn't necessary. You simply store the components where you want to, usually in the directory with your application executable.

For components that do need to be shared by a lot of other programs, you can create just one copy that is shared in the GAC, or Global Assembly Cache. This is explained in the article, GACUTIL - the Global Assembly Cache Utility. .NET keeps track of different versions here too. And Windows even gives you a customized display of the GAC. In the Windows Explorer view of the GAC, the subdirectory structure is hidden and the Paste option isn't even available because you must "install" an assembly in the GAC after it has been given a "strong name". See the About Visual Basic article SN.EXE - The Strong Name Tool for more information about how to do this.

And, for the hard core techies among you, you can also write programs that create new assemblies. The primary program that does this is the .NET compiler, but if you have the need, you can do the same thing. It's something that very few of you will ever need to do, but to get started, search for the System.Reflection.Emit namespace.

  1. About.com
  2. Computing
  3. Visual Basic
  4. The .NET Framework
  5. The .NET Framework - What is a .NET Assembly

©2014 About.com. All rights reserved.