Plug-in Framework (Part1): Marking Types for Consumption

Plug-in frameworks are extremely easy to create using the .NET architecture and the ability to dynamically load assemblies.  But after loading an assembly, there is still the process of enumerating various types for consumption.  There are several things you can do to mark types in an assembly for plug-in consumption and I'll attempt to cover each method along with some tips on when the method works well and when it starts to break down.


  1. Assembly Attribute Marking - Using assembly attributes to mark types
  2. Type Attribute Marking - Using attributes applied to individual types
  3. Base Class Enumeration - Enforcing types derived from a base type
  4. Interface Enumeration - Enforcing types implementing an interface
  5. Configuration Based Enumeration - Using configuration files to load plug-in assemblies and types
  6. Conclusion - Towards a more complete framework

1. Assembly Attribute Marking:
Assembly attribute marking is probably the easiest and most efficient way to mark types within an assembly for consumption.  This method entails the creation of a new attribute that you apply at the assembly level.  The attribute then names a type within the current assembly that should be loaded.  Currently the .NET Terrarium uses this method for loading creature assemblies.  While the Terrarium is arguably not a plug-in architecture, I'd beg to differ.  What are the benefits of loading plug-ins based on the assembly level attribute?

  • Determinate method for grabbing the necessary type information to instantiate a plug-in.  No enumeration.
  • The ability to mark types in multiple files in a single location in your source files.  All assembly attributes can share the same file.
  • The ability to leave out types that might appear as plug-ins to other methods.  Examples would be marking the final derived type as a plug-in, but leaving out your own base classes that might derive from the plug-in base class or leaving out types that might implement the plug-in interface, but aren't completed yet or that serve as interface thunks for other types.

Defining new attributes can be a bit tricky.  There are quite a few options, some of which are defined by an attribute that actually defines usage.  Definitely odd that it takes the use of an attribute to define a new attribute.  Sort of a chicken or the egg issue.  Here is a simple defintion for a new plug-in enumeration attribute.  Note that this attribute is making use of the single-use rule so that the attribute can only handle a single plug-in class per assembly.  If you take this out, the rules for grabbing the assembly attribute change.  We'll discuss both methods.

[AttributeUsage(AttributeTargets.Assembly, AllowMultiple=false, Inherited=false)]
public class PluginClassAttribute : Attribute {
    private string typeName;

    public PluginClassAttribute(string typeName) {
        this.typeName = typeName;
    public string TypeName { get { return typeName; } }

Now by applying this method at the assembly level of our plug-in assembly we can simply set the name of the type to load.  Note that you'll need to include any namespacing in order for the type name to be useful in grabbing the assembly type if you use namespaces.  We can extend this model by enabling an overloaded constructor that will take the Type of the plug-in instead of the type name.  I recommend using only one or the other of these methods.  Use the Type version whenever you want quick definitive access to the plug-in type.  But realize you'll need to check and make sure the Type reference is actually pointing to a type inside of your assembly.  Use the string version when you might be compiling your library and the plug-in type doesn't exist yet (think development builds).  Also, you won't have to check the Type to make sure the assembly matches since you'll be using the instance version of Assembly.CreateInstance in order to generate your object instance.

PluginClassAttribute[] attrs = (PluginClassAttribute[]) currentAssembly.GetCustomAttributes(typeof(PluginClassAttribute), false);
for(int i = 0; i < attrs.Length; i++) {

Getting the attributes containing your plug-ins is pretty easy.  Note that I've just called GetCustomAttributes on the assembly my plug-ins are stored in.  By passing in the Type of the attribute I'm looking for, only those types are grabbed, and I can use this to do a quick cast of the returned object[].  In the case of our plug-in attribute, we'll always return either 0 or 1 attribute in the array.  However, by setting the AllowMultiple flag to true you can enable additional instances of the attribute to be applied to your assembly.

[AttributeUsage(AttributeTargets.Assembly, AllowMultiple=false, Inherited=false)]

Since this article is only about marking your types for consumption I won't go any further into the process of loading plug-ins from an assembly (wait for part 2 I guess).  Assembly attributes are extremely easy to create, allow a good deal of customization using overloaded constructors, and are quick to grab out of an assembly for those time critical applications.

2. Type Attribute Marking:
Type attribute marking loses some of the benefits of assembly attribute marking in terms of plug-in loading speeds, but has a completely different use that assembly level attributes don't have.  Type attribute marking can be used on the class level to mark individual types for consumption, but it can also be used to mark members of types for consumption.  In other words, rather than just defining a type that should be instantiated, we can go one step further and even define a method (possibly a static method) that should be used to create an instance of the pug-in.  Some of the greatest uses of Type marking attributes are in Visual Studio, where they make liberal use of attributes to define custom type editors, whether or not properties are browsable (this is another cool item that can be included in plug-ins), and default values (wow plug-ins can really gain a lot from the design principles in VS).

I'm moving a bit away from the subject at hand though, and that is loading plug-ins, not actually operating on them (part 3 or 4 anyone? ;-) or controlling how the user interfaces with them once they are loaded.  Type attributes have all of the benefits of Assembly attributes, except for one.  They require that you enumerate all types and then search those types for the necessary attributes.  Since you have to enumerate all types and then access their meta-data, this becomes the slowest option of all 4.  Since we'll need a method to enumerate types in an assembly for later sections, we'll define a piece of common code now.

Type[] allTypes = currentAssembly.GetTypes();
for(int i = 0; i < allTypes.Length; i++) {
    Type possible = allTypes[i]; // Here is the access point

That is fine and good, but how do we find out which types match our criterion?  Well, we need to make sure those types are now marked by a new attribute.  This new attribute doesn't need any parameters in the constructor, since it will be attached to the appropriate class, and we can only allow a single instance per class, so we are back to AllowMultiple = false.  Once the attribute is defined and attached to a class, the code to check for this looks astoundingly the same as that used to examine assembly attributes, except now we have to rely on the Attribute static for GetCustomAttribute since one doesn't exist on Type (odd to say the least).

[AttributeUsage(AttributeTargets.Class, AllowMultiple=false, Inherited=false)]
public class PluginMarkerAttribute : Attribute {
    public PluginMarkerAttribute() {}

public class FooBar {
    public void DoAttrs() {
        Type[] allTypes = currentAssembly.GetTypes();
        for(int i = 0; i < allTypes.Length; i++) {
            Type possible = allTypes[i]; // Here is the access point
            PluginMarkerAttribute typeAttrs = Attribute.GetCustomAttribute(possible, typeof(PluginMarkerAttribute)) as PluginMarkerAttribute;
            if ( typeAttrs != null ) {

That does look a bit harder than assembly attributes, so why would you use it?  Well, it does mean you can put your attribute in the same source file as the plug-in class.  You can also do this with assembly attributes, but here the attribute is actually being applied to the class, so it is very visible.  I'd argue this isn't that grand, but some people like it.  Other than that it operates just like an assembly attribute with full protection against accidentally loading non plug-in classes that inherit a base class or implement an interface.

3. Base Class Enumeration:
This is a very popular form of grabbing plug-in classes.  By enforcing a base class, you can allow your plug-ins to inherit some base functionality, while at the same time forcing them to implement various methods and properties that your architecture requires.  Because they employ this method enforcement they are often used over attributes for plug-in selection.  I think, however, that attributes are still a better selection criterion, while base classes can be layered on as an additional constraint.  That way you get the best of both worlds.  So let's take a quick look at what base classes have to offer.

  • Non-determinant way to pick out plug-in types.  Since the assembly must be enumerated, this method can be slow.
  • Type system based enforcement of required methods and properties that might be needed by the plug-in system.  Can be used in conjunction with an attribute based marking system.
  • If only the base class is used during enumeration, there is the possibility of loading unwanted types as plug-ins.  For instance, someone tries to load the assembly used to define the root class for the plug-in system as a plug-in.  This has actually happened in the Terrarium, but we were checking assembly attributes and never missed a beat.
  • Faster than examining type marking attributes unless the subclass depth is extremely deep.  Someone can catch me on this, since the CLR probably heavily optimizes access to the subclass tree such that it would take a really deep tree before meta-data grabs became faster.
  • A plug-in can only be of one type in the plug-in architecture because plug-ins are identified by their base class.  Without multiple inheritance a single plug-in can't perform multiple roles out of the box unless the plug-in system supports an additional support system in code.  Interface systems beat this since a single plug-in can implement any amount of interfaces.
  • Versioning sucks.  If the base class changes, so do the plug-ins have to be recompiled.
  • Easier to implement than interface based plug-ins when plug-ins can share commmon logic methods that might be difficult to implement each time you write a new plug-in.  Can be overcome by helper classes.

Wow, actually a lot of those points are against using base classes for plug-ins in general, rather than just being against the loading system.  Every method has it's place though, and if you plan on only having a few types per assembly, and want to use type system enforcement of required methods and properties then a class system is the way to go.  The ability to add base class functionality means all plug-ins will inherit some degree of shared abilities that might make the coding experience a bit easier for new plug-in developers.  This all adds up to a quickly developed and rich plug-in architecture, that lacks a good deal of future extensibility.  Definitely good for one off projects with small support lifetimes.  Checking for the types becomes easy since we've already defined the type enumeration system.  Simply check to make sure the given type actually inherits from your base.  The Type class provides an instance method for just this purpose, IsSubclassOf().

public class BaseFooBar {

public class FooBar2 : BaseFooBar {
    public void DoSubclass(Assembly currentAssembly) {
        Type[] allTypes = currentAssembly.GetTypes();
        for(int i = 0; i < allTypes.Length; i++) {
            Type possible = allTypes[i]; // Here is the access point
            if ( possible.IsSubclassOf(typeof(BaseFooBar)) ) {

4. Interface Enumeration:

I think interfaces are the way to go when defining a really solid plug-in architecture.  And not just on the plug-in side of the fence, you can use the same interface style methods to extend helper functions over to the interface based plug-ins to simplify the process of writing code for tedious tasks.  In addition, they allow the quick and easy advancement of the plug-in system through revisions while also allowing a single plug-in class to implement multiple plug-in interfaces at once.  All of these are great features at the expense of a much more complex plug-in system overall and they still have delayed load times and enumeration of type requirements.

  • Non-determinant way to pick out plug-in types.  Since the assembly must be enumerated, this method can be slow.
  • Has similiar type enforcement system to the base class marking.
  • Can also load unwanted types if not used with an attribute marking system.
  • Possibly faster than examining type marking attributes.  Interface mapping isn't something I'm that familiar with and could be slow when searching types for multiple interfaces.
  • Plug-ins can now implement multiple plug-in functions.  A single type can now be a UI plug-in, menu plug-in, and contain action or job plug-ins all at once.  This is powerful.
  • Versioning is much better using interfaces.  The base application can change by adding a new interface.  Old code can still work, while new code can implement the new interfaces.  Upgraded code can simply remap previously written functions to match the new interface and provide updates where needed.
  • Requires some form of helper class to provide common functionality.  Providing access to this helper class can often be a PITA.  Helper class needs to be interfaced in order to provide versioning across the board.  The type system gets complex.
  • Forces plug-in designers to implement all methods of the interface.  Complex plug-in interfaces with many methods will result in a long development time.  Similarly a base class system can provide defaults for cases where plug-ins can implement a large amount of functionality through many methods/properties.

You can definitely see that while interfaces provide a more robust system for a plug-in architecture, they also make it much more complicated if you want to handle lots of different issues.  It is nice to note that interfaces are just as easy to check for as a base class.  The Type class again steps in with an instance method to do our dirty work, IsAssignableFrom().  Basically, we grab the type of our interface and see if it is assignable from the current type being enumerated out of the assembly.  We could have used the same method with base classes, but nah!

public interface IFooBar {

public class FooBar3 : IFooBar {
    public void DoAssignableFrom(Assembly currentAssembly) {
        Type[] allTypes = currentAssembly.GetTypes();
        for(int i = 0; i < allTypes.Length; i++) {
            Type possible = allTypes[i]; // Here is the access point
            if ( typeof(IFooBar).IsAssignableFrom(possible) ) {

I have wrapped all of this up into a little zip, but I have to find a place to toss it up [insert link start]here[insert link end].  You guys will have to remind me.

5. Configuration Based Enumeration
Sami Vaaraniemi
pointed out that configuration files can be used to probe for plug-ins.  This is actually the most popular way of dynamically loading types and is used by the CLR in various forms.  The primary form is used to choose which libraries your application will load when running so that you can select from several options (maybe debug versus release builds).  Special manifest files do this mapping and are capable of hooking your application up to a certain version of the .NET run-time, pick a particular assembly version out of the GAC, or even promote a specific version of your library to accept requests for a previous version.  Generally the following rules apply to configuration based enumeration.

  • Determinant way to mark which assemblies and which types have plug-in information.  Generally you need to have the user select plug-ins, use a special directory where all plug-ins are placed, or simply enumerate all assemblies.  Sometimes this can be impossible since an assembly might not even have an extension that would mark it as an assembly.  For instance, you could rename the file “MyGraphicsEngine.plugin“ in order to demonstrate that all plugins have a .plugin extension, but normally assemblies are denoted by the .dll or .exe extension.
  • No Type-Enforcement is available when doing configuration based enumeration.  Or I take that back, no built-in type enforcement.  In this way, a user can mark any type within any assembly as a plug-in.  It is up to your code to enforce some set of rules, perhaps using one of the first 4 methods of marking types for consumption.
  • User does NOT need the ASSEMBLY in order to investigate plugins.  This is huge.  By having a centralized config file on some web server, the user has access to as many plugins as are defined, and can enumerate them without having the assemblies on disk.  As the user makes use of the various plugins they can be dynamically downloaded as needed.  Part 2 of the plug-in framework documentation will cover this process.
  • This is the fastest method for enumerating plug-in types.  Only plug-in assemblies need to be loaded, and only plug-in types are probed.  No need to enumerate all assemblies and look for plug-ins and no reason to enumerate all types.  This is similar to using assembly attributes for marking without the need to first load the assembly to get at the attributes.
  • Built in versioning is available since developers/users can select which assemblies and which plug-ins to load.  If you have multiple versions, just point the config file at the latest version.
  • Need to have a configuration file that ships with the application to know which plug-ins to load.  This kind of sucks, and you can build a default configuration into your assembly in the case that one doesn't exist.  However, since you are loading plug-ins there are already additional files to copy around so this might not be such a big deal.
  • Have to educate users to add plug-ins into the configuration file.  This can be a real PITA since most users won't want to mess with configuration files.  You can give them a built in tool for this feature, such as the Visual Studio assembly references dialog where all known plug-ins are there by default, and new plug-ins can be browsed for and then added to the known plug-ins list.
  • In systems where plug-in assemblies are shadow-copied you have to make sure not to load them multiple times when a user loads multiple plug-ins from the same assembly.  This is simply infrastructure work and requires that you group known plug-ins to optimize the assembly load process or keep a list of already loaded assemblies.

One great thing about configuration files is that they are generally very easy to use.  I had originally slated the use of configuration files for Part 2 of the plug-in framework, but reconsidered that it might be better examined in two parts, as both an enumeration method for plug-ins and a method for storing known plugins and to define where plugins need to be loaded from.  We'll discover this first use using a simple example.

Say your application stores all assemblies within the same directory for simplicity.  You may actually have assemblies for resources, your own libraries, RCW's for various platform features, and finally some plug-in libraries.  Under normal circumstances you'd have to load and enumerate all of these assemblies in order to discover plug-ins.  By using a configuration file you can specify which assemblies to load (this is part of Part 2 as to how the configuration file is used to load assemblies), and you can specify which types from that assembly to load (this is the important part).  Normally this might look something like:

  <plugin assembly=“CommercialPlugins“ type=“CommercialPlugins.GraphicsFilters.RedFilter“ />
  <plugin assembly=“CommercialPlugins“ type=“CommercialPlugins.GraphicsFilters.GreenFilter“ />
  <plugin assembly=“CommercialPlugins“ type=“CommercialPlugins.GraphicsFilters.BlueFilter“ />

The assembly is first named and then finally the type.  There are many methods for doing this, including using an fully qualified assembly name, but I always find breaking things out into parts to be easier for end users.  Another configuration file may have a special assembly tag, that in turn holds plugin tags that mark the types.  This is a better grouping mechanism so that all types with the same assembly are clearly marked in a hierarchical manner within the configuration file.

  <assembly name=“CommercialPlugins“>
    <plugin type=“CommercialPlugins.GraphicsFilters.RedFilter“ />
    <plugin type=“CommercialPlugins.GraphicsFilters.GreenFilter“ />
    <plugin type=“CommercialPlugins.GraphicsFilters.BlueFilter“ />

If you are writing code that builds lists of known plug-ins this format can be much easier to use.  Once your format is specified loading plug-ins is just a matter of interrogating your configuration file and then directly loading the types without any actual reflection based enumeration.  Normally, the plugins section will be located amongst other configuration setting, so it will just be a matter of getting to the appropriate portion of the XML and interrogating your structure.  I'll leave the code for this out for now unless someone requests that I write it.

Configuration files are just plain fast, but they lack any form of security.  Anyone can muck with files on disk and then load your application.   Anyone can delete the file and all of a sudden your application doesn't load any plugins at all.  So the mantra for configuration files is to have a back-up plan in case the file doesn't even exist.  If the file does exist, use some other form of marking in order to verify plugins while loading them.  Always provide the user with a method of selecting new assemblies and enumerating the plugins manually.  Remember, the user isn't going to ILDasm your assembly just to figure out which types they want to load.

It is nice to note that configuration can be stored anywhere though.  You can make use of the registry (which I recommend against, because it is hard for users to access if they need to), a flat file on the disk, loading the configuration from a database, or even loading it from a website.  The final scenario, loading from a website, is one of the most powerful plugin features you could possibly think of.  Since the plugins are already enumerated, you don't need the actual assembly to determine which plugins are available.  In this manner large amounts of plugins can be placed on a server and downloaded on an as needed basis.  When Sami mentioned configuration files in his comment, this was the first use that came to mind.

6. Conclusion:
Concluding this article, I want to point out what my intentions are.  I'm really intersted in the security ramifications of a plug-in system, and how one might protect a user by allowing them to run arbitrary code without having to worry about their system going down the toilet because of some dude speaking hacker cracker that thinks writing a plug-in with a cool name and a bad agenda is the thing to do.  It is going to take me 5 or 6 articles to build up to the security section though, since I want a solid plug-in framework to work from, and I'm figuring some of the work I do along the way might be interesting to other folks.  Hopefully I'll be able to punch this out within a week or two.

So what methods will I be using in order to mark my types?  Well, I really like the idea of using the assembly attribute marking system, because it is so fast in identifying which types need to be loaded even when thousands of types exist.  If you are loading say 50 plug-in libraries then you'll definitely appreciate this speed.  I'll mix that with the interface constraint system for actually defining how a type is going to interact with the system and become a plug-in.  Since you'll be able to mark non plug-in types using this method, I'll be writing all of the code in Part 2 to load up your assemblies, prevent locking, and get a collection of plug-in types.  I'll probably go into grabbing some basic information off of the types as well, using either attributes (which can't be enforced) or interface properties (enforcable), I just don't know what I'm going to use yet.

Published Wednesday, January 21, 2004 3:05 AM by Justin Rogers
Filed under:


Wednesday, January 21, 2004 2:03 PM by chadb

# re: Plug-in Framework (Part1): Marking Types for Consumption

That's good stuff...
Thursday, May 6, 2004 2:20 AM by Claus Konrad

# re: Plug-in Framework (Part1): Marking Types for Consumption

Hi Justin

What is happening to the rest of the articles?
We are looking forward to read the remaining 4 chapters of the Plugin-framework articles series...

Thursday, March 18, 2010 5:44 AM by shivamseo

# re: Plug-in Framework (Part1): Marking Types for Consumption

such a mindwell plugin fremwork i like to follow it such easy way to understand .

Thursday, March 18, 2010 5:46 AM by shivamseo

# re: Plug-in Framework (Part1): Marking Types for Consumption

hi good article but i have one doubt about bool format ll u please guide me how can i improve it.

Thursday, January 12, 2012 2:53 PM by Software Development

# re: Plug-in Framework (Part1): Marking Types for Consumption

great approach to plugin frameworks

Tuesday, February 7, 2012 10:49 AM by oem software

# re: Plug-in Framework (Part1): Marking Types for Consumption

lNLjHm Yeah, in my opinion, it is written on every fence!!....

Tuesday, May 8, 2012 5:09 AM by service

# re: Plug-in Framework (Part1): Marking Types for Consumption

wow, awesome post. Really Cool.

Thursday, May 10, 2012 3:42 AM by social

# re: Plug-in Framework (Part1): Marking Types for Consumption

xActUI Really informative article post.Thanks Again. Much obliged.

Friday, May 11, 2012 5:45 AM by seo

# re: Plug-in Framework (Part1): Marking Types for Consumption

iGrqUh Im thankful for the post.Thanks Again. Awesome.

Wednesday, May 23, 2012 3:32 AM by external

# re: Plug-in Framework (Part1): Marking Types for Consumption

More specifically, an external process will add a new Message to this application's database. I will need a job that watches for new messages, and then pushes them through the Process.

Sunday, December 16, 2012 10:43 AM by Hinson

# re: Plug-in Framework (Part1): Marking Types for Consumption

I read this article fully regarding the difference of most up-to-date and previous

technologies, it's awesome article.

Monday, December 24, 2012 7:15 AM by Peralta

# re: Plug-in Framework (Part1): Marking Types for Consumption

I found your article very thought provoking. The manner it was written

made me look at things out of an alternative angle and think about what I originaly thought, why not visit us .

I will definately be back again.

Tuesday, January 1, 2013 6:01 AM by Lightner

# re: Plug-in Framework (Part1): Marking Types for Consumption

Hello colleagues, its fantastic article about teachingand fully

defined, keep it up all the time.

Thursday, January 3, 2013 10:05 AM by Baber

# re: Plug-in Framework (Part1): Marking Types for Consumption

Hey there! Great post! Please when I will see a follow up!

Tuesday, January 8, 2013 9:30 AM by Cloud

# re: Plug-in Framework (Part1): Marking Types for Consumption

Does your blog have a contact page? I'm having problems locating it but, I'd like to send you an email.

I've got some ideas for your blog you might be interested in hearing. Either way, great website and I look forward to seeing it improve over time.

Thursday, January 10, 2013 7:55 PM by Rinehart

# re: Plug-in Framework (Part1): Marking Types for Consumption

omg! can’t imagine how fast time pass,

after August, ber months time already and Setempber is that the first Christmas season in my place, I actually love it!

Wednesday, January 16, 2013 10:02 PM by backlinks service

# re: Plug-in Framework (Part1): Marking Types for Consumption

Really appreciate you sharing this blog.Much thanks again. Much obliged.

Friday, January 18, 2013 5:53 PM by Lopez

# re: Plug-in Framework (Part1): Marking Types for Consumption

Right now it seems for instance Movable Type is the best blogging platform available right now.

(from what I’ve read) Is that what you’re using on your blog?

Friday, February 1, 2013 4:07 AM by pills for weight loss

# re: Plug-in Framework (Part1): Marking Types for Consumption

NHIuO9 Enjoyed every bit of your post.Thanks Again. Much obliged.

Friday, February 1, 2013 4:15 PM by pills for weight loss

# re: Plug-in Framework (Part1): Marking Types for Consumption

SxGYkQ Enjoyed every bit of your article post.Really looking forward to read more. Will read on...

Monday, February 11, 2013 1:22 PM by Allred

# re: Plug-in Framework (Part1): Marking Types for Consumption

Hmm it seems something like your site ate my first

comment (it was extremely long) so I guess I’ll just

sum it up what I submitted and say, I’m thoroughly enjoying your blog.

I too am an aspiring blog writer conversely I’m still new to everything.

Do you have any tips for rookie blog writers? I’d certainly appreciate it.

Saturday, March 23, 2013 12:16 PM by Crouse

# re: Plug-in Framework (Part1): Marking Types for Consumption

So there you can design a trader 247 nurse.

High on the price spread and its habits, sleep disorders for

several years. If used as animal feed, gained 94 cents, penny Trader 247 is sweet

enough. 79Market cap: $217 4 percent after the end.

Friday, April 26, 2013 4:18 PM by wolemrfjqq

# re: Plug-in Framework (Part1): Marking Types for Consumption

birdupstairs undefiledelationpurloinunequivocalabove in in

Friday, May 3, 2013 6:12 AM by Blair

# re: Plug-in Framework (Part1): Marking Types for Consumption

Clinical studies pure green coffee extract were successfully done, and the like.

According to the pure green coffee extract American Journal of Clinical Nutrition also shows that the tribe, which use Irvingia on a daily basis

are experiencing which far outweigh the risks, experts believe.

The ingredients in these pills will also not bring

you immediate results. A few ingredients, for these are not always that healthy for you, but can still jog for 30mins on the treadmill for hours.