Search code examples
c#.netcominteropcom-interop

How to check if type from assembly is ComVisible


I'm writing an add-in manager for Enterprise Architect.

When loading an assembly (addin dll) I need to know which of the types defined in the assembly is COM visible, so I can add the required registry keys to register it for COM interop.

Here's what I have have so far:

public EAAddin(string fileName):base()
{
    //load the dll
    this.addinDLL = Assembly.LoadFrom(fileName);
    //register the COM visible classes
    this.registerClasses(this.addinDLL);
    //load referenced dll's
    foreach (AssemblyName reference in this.addinDLL.GetReferencedAssemblies())
    {
          if (System.IO.File.Exists(
                 System.IO.Path.GetDirectoryName(this.addinDLL.Location) + 
                    @"\" + reference.Name + ".dll"))
          {
            Assembly referencedAssembly = System.Reflection.Assembly.LoadFrom(System.IO.Path.GetDirectoryName(this.addinDLL.Location) + @"\" + reference.Name + ".dll");
            //register the COM visible classes for the registered assembly
            this.registerClasses(referencedAssembly);
// ... more code ...
private void registerClasses (Assembly assembly)
{
    foreach (Type type in assembly.GetExportedTypes()) 
    {
            register(type, assembly);
    }
}

private void register(Type type, Assembly assembly)
{
    var attributes = type.GetCustomAttributes(typeof(ComVisibleAttribute),false);
    if  (attributes.Length > 0)
    {
        ComVisibleAttribute comvisible = (ComVisibleAttribute)attributes[0];
        if (comvisible.Value == true)
        {
            //TODO add registry keys here
        }
    }            
}

This doesn't work as type doesn't seem to contain a ComVisibleAttribute.

Anyone know how to figure out which of the ExportedTypes in an Assembly are COM visible?


Solution

  • Thanks to the comment from Paulo I was able to figure it out. The type only has a ComVisibleAttribute if it is different from the Assembly default.

    So this operation (called on one of the types returned Assembly.GetExportedTypes()) by seems to do the trick

    /// <summary>
    /// Check if the given type is ComVisible
    /// </summary>
    /// <param name="type">the type to check</param>
    /// <returns>whether or not the given type is ComVisible</returns>
    private bool isComVisible(Type type)
    {
        bool comVisible = true;
        //first check if the type has ComVisible defined for itself
        var typeAttributes = type.GetCustomAttributes(typeof(ComVisibleAttribute),false);
        if  (typeAttributes.Length > 0)
        {
             comVisible = ((ComVisibleAttribute)typeAttributes[0]).Value;
        }
        else
        {
            //no specific ComVisible attribute defined, return the default for the assembly
            var assemblyAttributes = type.Assembly.GetCustomAttributes(typeof(ComVisibleAttribute),false);
            if  (assemblyAttributes.Length > 0)
            {
                 comVisible = ((ComVisibleAttribute)assemblyAttributes[0]).Value;
            }
        }
        return comVisible;
    }