C Sharp

Working with Assemblies and Modules

Assemblies will be covered in much more detail in Chapter 18, "Working with Assemblies." For the purpose of this conversation, it's enough to know that an assembly is a physical file that consists of multiple .NET PE files. An assembly's main benefit is that it enables you to semantically group functionality for easier deployment and versioning. The .NET runtime's representation of an assembly (and the apex of the reflection object hierarchy) is the Assembly class.

You can do many things with the Assembly class. Here are some of the more common tasks that we'll be looking at: -

  • Iterate through an assembly's types
  • List an assembly's modules
  • Determine identification information, such as the assembly's physical file name and location
  • Inspect versioning and security information
  • Retrieve the assembly's entry point

Iterating Through the Types of an Assembly

To iterate through all of the types for a given assembly, you need only instantiate an Assembly object and then request the Types array for the that assembly. Here's an example: -

using System;
using System.Diagnostics;
using System.Reflection;
class DemoAttr : System.Attribute
{
}
enum DemoEnum
{
}
class DemoBaseClass
{
}
class DemoDerivedClass : DemoBaseClass
{
}
class DemoStruct
{
}
class GetTypesApp
{
    protected static string GetAssemblyName(string[] args)
    {
        string assemblyName;
        if (0 == args.Length)
        {
            Process p = Process.GetCurrentProcess();
            assemblyName = p.ProcessName + ".exe";
        }
        else
            assemblyName = args[0];
        return assemblyName;
    }
    public static void Main(string[] args)
    {
        string assemblyName = GetAssemblyName(args);
        Console.WriteLine("Loading info for " + assemblyName);
        Assembly a = Assembly.LoadFrom(assemblyName);
        Type[] types = a.GetTypes();
        foreach(Type t in types)
        {
            Console.WriteLine("\nType information for: " +
                              t.FullName);
            Console.WriteLine("\tBase class = " +
                              t.BaseType.FullName);
        }
    }
}
NOTE
If you're attempting to run code that needs security clearance-such as code that uses the reflection API-over an intranet, you'll need to modify policy. One means of doing this is with the Code Access Security Policy tool (caspol.exe). Here is an example of using caspol.exe:
caspol -addgroup 1.2 -url "file://somecomputer/someshare/*"
    SkipVerification

This example grants additional permission-in this case, SkipVerification-based on the URL of the code being run. Note that you could also modify policy for all code in a given zone or only for a particular assembly, based on cryptographic signature or even the hash of the bits. To view the valid arguments for the caspol.exe utility, either type caspol -? at a command prompt or use the MSDN online documentation.

The first part of the Main method isn't really interesting-that code determines whether you passed an assembly name to the application. If you did not, the Process class's static GetProcessName method is used to determine the name of the currently executing application.

After that you start to see how easy most of the reflection tasks are. The easiest way to instantiate an Assembly object is to call the Assembly.LoadFrom method. This method takes a single argument: a string representing the name of the physical file that you want to load. From there, a call to the Assembly.GetTypes method returns an array of Type objects. At this point, we have an object describing every single type in the entire assembly! Finally, the application prints its base class.

Here's the output from the execution of this application when you either specify the gettypes.exe file or don't pass any arguments to the application: -

Loading info for GetTypes.exe
Type information for: DemoAttr
    Base class = System.Attribute
Type information for: DemoEnum
    Base class = System.Enum
Type information for: DemoBaseClass
    Base class = System.Object
Type information for: DemoDerivedClass
    Base class = DemoBaseClass
Type information for: DemoStruct
    Base class = System.Object
Type information for: AssemblyGetTypesApp
    Base class = System.Object