views:

164

answers:

4

I'm looking for a more efficient way to find a type in an Assembly that derives from a known specific type. Basically, I have a plugin architecture in my application, and for the longest time we've been doing this:

For Each t As Type In assem.GetTypes()
    If t.BaseType Is pluginType Then
        'Do Stuff here'
    End If
Next

Some of the plugins have a large number of types and we're starting to see this take a few seconds. Is there any way I can just ask for all types that have a BaseType of "pluginType"?

EDIT: I over-simplified my code sample. I was using .GetExportedTypes() in my actual code. However, I alot of classes were marked as Public, so it wasn't helping too much. I combed through the projects and marked everything "Friend" except for the actual plugin class, and it still takes nearly the same amount of time to examine the assemblies. I cut maybe 100 ms off of 1.3 seconds (which is less than 10%). Is this just the minimum time I have to deal with? I'd also tried the Assembly Attribute suggestion and it still didn't yield much difference (maybe 100ms again). Is the rest of the time the overhead I have to pay to load assemblies dynamically?

+1  A: 

Assembly.GetExportedTypes() only returns public classes. Could this help?

BC
Please see updated question...
Bob King
+4  A: 

First off, you may try using GetExportedTypes() to narrow down the list of potential types. Other than that, there's no way you can speed up the iteration process. You can, however, include a plugin mainfest which would specify the exact type (types) of plugins within a particular assembly:

<manifest>
    <plugin type="FooBar.Plugins.BazPlugin, FooBar" />
</manifest>

so that you'd be able to do Type.GetType(string)

IPlugin plugin = (IPlugin)Type.GetType("manifest/plugin/@type" /* for the sake of this discussion */);
Anton Gogolev
Please see updated question...
Bob King
A: 

Our plug-in system utilises attributes to identify the plug-in types. We then just scan the assembly for the specific attribute.

Jeff Yates
Please see updated question...
Bob King
+1  A: 

Solution from mono-devel mailing list post by Jonathan Pryor and Plug-in Framework (Part1): Marking Types for Consumption : use assembly-level attributes.

In short, you'd add a new attribute:

[AttributeUsage(AttributeTargets.Assembly, AllowMultiple=true)]
class PluginAttribute : Attribute {
  public PluginAttribute (Type type) {this.Type = type;}
  public Type Type {get; private set;}
}

Then specify this attribute at the assembly level:

[assembly:Plugin (typeof(Plugin1))]
[assembly:Plugin (typeof(Plugin2))]

Then query the assembly for all the PluginAttributes:

Assembly a = ...;
PluginAttribute[] plugins =
    (PluginAttribute[]) a.GetCustomAttributes (
        typeof(PluginAttribute), true);
foreach (var plugin in plugins)
// plugin.Type is the type to use as a plugin

This can be significantly faster than using Assembly.GetTypes() / Assembly.GetExportedTypes(), as only the types which are listed in [assembly:Plugin] attributes actually need to be loaded, which can significantly decrease the amount of memory consumed (depending on the number of types in the assembly).

skolima