Programmatically Generating an Interop Assembly

The same functionality that is provided with the tlbimp utility is exposed in the TypeLibConverter class. To use this class, load a type library description. Listing 8.5 shows the most straightforward method to load a type library. The full source to this sample is available in the TypeLibraryConversion directory.

Listing 8.5. Loading a Type Library
private enum RegKind
{
    RegKind_Default = 0,
    RegKind_Register = 1,
    RegKind_None = 2
}

[ DllImport( "oleaut32.dll", CharSet = CharSet.Unicode, PreserveSig = false )]
private static extern void LoadTypeLibEx(String strTypeLibName,
                                         RegKind regKind,
                                         [MarshalAs(UnmanagedType.Interface)]
                                         out Object typeLib);
[STAThread]
static void Main(string[] args)
{
    Object typeLib;
    LoadTypeLibEx( "COMTypes.dll", RegKind.RegKind_None, out typeLib );
    if( typeLib == null )
    {
        Console.WriteLine( "LoadTypeLibEx failed." );
        return;
    }

No easy way exists to retrieve the type library—or more specifically the ITypeLib interface—from a file. You can use DllImport and the P/Invoke services (covered in Chapter 7, “Leveraging Existing Code—P/Invoke”) to call LoadTypeLibEx. LoadTypeLibEx, a Win32 function, is exactly applicable to this situation. LoadTypeLibEx reads in the file from the path specified. If it is a TLB file (a stand-alone type library), then it is loaded directly. If it is a DLL or EXE file, it locates the first resource that has a type of ITypeLib, loads the type library information, and returns an ITypeLib interface to that loaded type library information. If your DLL or EXE has multiple type libraries, you might need to append an integer to the path to indicate which type library you want to load (see the Win32 documentation on LoadTypeLib). Notice that in Listing 8.6, this function is called with an argument of RegKind.RegKind_None, indicating that the type library will not be registered, just loaded. If this function succeeds, then you have an ITypeLib interface.

With an ITypeLib interface, you can proceed with the conversion, as shown in Listing 8.6. The source that corresponds to this listing is in the TypeLibraryConversion directory.

Listing 8.6. Converting a Type Library
        TypeLibConverter c = new TypeLibConverter();
        ConversionEventHandler eventHandler = new ConversionEventHandler();
        AssemblyBuilder asm = c.ConvertTypeLibToAssembly( typeLib, "Interop.COMTypes.dll",
 0, eventHandler, null, null, null, new Version("1.0.0.0") );
        asm.Save( "Interop.COMTypes.dll" );
    }
}
public class ConversionEventHandler : ITypeLibImporterNotifySink
{
    public void ReportEvent( ImporterEventKind eventKind,
                                 int eventCode,
                                 string eventMsg )
    {
        // Simply report that this method was called.
        // This mimics the /verbose option of the tlbimp utility.
        Console.WriteLine("ReportEvent {0} : {1} ", eventKind, eventMsg);
    }

    public Assembly ResolveRef( object typeLib )
    {
        // Resolve reference here and return a correct assembly...
        Console.WriteLine("ResolveRef");
        return null;
    }
}

The ConvertTypeLibToAssembly method of the TypeLibConverter class performs most of the work in converting a type library to an assembly. A couple of things are worth noting about this code snippet—in particular, this method call. Notice that the path has been hard coded to the destination of the interop assembly. Naturally, in a really useful application, you would make this a variable or have a heuristic to generate an output filename. Notice, too, that no flags have been passed as the third argument to ConvertTypeLibToAssembly. The available flags are as follows:

  • PrimaryInteropAssembly— This mimics the tlbimp /primary option flag in creating a primary interop assembly (PIA).

  • SafeArrayAsSystemArray— This is like the tlbimp /sysarray option flag. It allows for marshaling SAFEARRAY arguments as System.Array. The default behavior is to wrap a SAFEARRAY argument as a VARIANT containing SAFEARRAY.

  • UnsafeInterfaces— This is like the tlbimp /unsafe option flag. It removes the CLR stack crawl for permission to run unmanaged code. This results in some performance benefit at the expense of opening a rather egregious security hole.

The next argument is a reference to an implementation of the ITypeLibImporterNotifySink interface. The user can be notified of events that are called as the conversion process proceeds. This is much like the tlbimp /verbose option flag. The next two arguments deal primarily with the creation of a primary interop assembly. The first of these security arguments is a byte array containing the public key for the interop assembly. The next of these security arguments is StrongNameKeyPair, which contains the public and private keys to be associated with the interop assembly. These arguments roughly correspond to the tlbimp /publickey, /keyfile, and /keycontainer option flags. In this sample code, null has been passed to each of these security arguments so that the created assembly will not be a PIA. The next argument is a namespace for the assembly. This is similar to the tlbimp /namespace option flag. Again, null has been passed to indicate that no namespace should be associated with this interop assembly. Finally, the last argument is the version of the interop assembly to be created. This is similar to the tlbimp /asmversion option flag. An instance of Version has been passed for this argument, which will create an interop assembly with a version of 1.0.0.0.

When the ConvertTypeLibToAssembly succeeds, it creates an Assembly (specifically an AssemblyBuilder) object. The only thing left to do is write the Assembly out to a file on disk, which is done with the Save method on the AssemblyBuilder class. This code is woefully lacking in error handling, but it illustrates a programmatic way of accomplishing the same functionality that tlbimp provides.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.140.108