By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
439,972 Members | 1,454 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 439,972 IT Pros & Developers. It's quick & easy.

References for designing a "Plug-In" software architecture

P: n/a
This may not be a direct C# question, but since I'll be using using C# for
development, I thought I'd pose the question here.

I'll soon be involved in the design of a new software product that will
employ a software "Plug-In" architecture. Taking the plug-in route will
give us a design that can adapt to, as yet, undefined future requirements
(within the scope of the plug-in interface spec of course). In the past
I've done this with COM components that register themselves in a list of
available code resources. However, I'd be interested to hear how any of
you have approached the design for a software plug-in architecture, and/or
any references you may have used to make your design decision.

Gary ...

Nov 16 '05 #1
Share this Question
Share on Google+
6 Replies


P: n/a
one resource comes to mind is a blog entry on lightweight container pattern already available in .NET.

http://weblogs.asp.net/cazzu/archive....aspx#FeedBack

in the article, it also link to a few architecture patterns implemented in java.

"Gary James" wrote:
This may not be a direct C# question, but since I'll be using using C# for
development, I thought I'd pose the question here.

I'll soon be involved in the design of a new software product that will
employ a software "Plug-In" architecture. Taking the plug-in route will
give us a design that can adapt to, as yet, undefined future requirements
(within the scope of the plug-in interface spec of course). In the past
I've done this with COM components that register themselves in a list of
available code resources. However, I'd be interested to hear how any of
you have approached the design for a software plug-in architecture, and/or
any references you may have used to make your design decision.

Gary ...

Nov 16 '05 #2

P: n/a
doing an interface based plugin system is remarkably easy ...

a few questions though...

1) do you want to isolate the plugins ? i.e. seperate appdomains
2) are the plugins to be local or do they need to be capable of being
distributed objects ?

the simplest route for plugins providing you don't want either of the above
is just to run through an assembly getting the types ... you can then run
through the interfaces that the type supports .. supporting inheritance
chains as well is not very difficult. You would then up with a factory
method that you pass in a type to ... it would return the objects in the
assemblies you told it to look in (i.e. a subdirectory). You could also
strongly type these factories by subclassing specific plugin factories ... I
would also recommend lazy loading this info and hitting a cache the second
time through as it can be slow to get this info (esp with debug symbols).

slightly modified example (only loads plugins with attribute but loads them
for all interfaces they support) ...

public void LoadAssembly(string _AssemblyPath) {
Assembly PluginAssembly;
try {
PluginAssembly = Assembly.LoadFrom(_AssemblyPath) ;
}
catch (Exception Ex) {
throw new System.Exception("Unable to load assembly " + _AssemblyPath,
Ex) ;
}
//have assembly get all types.
System.Type [] AssemblyTypes = PluginAssembly.GetTypes() ;
Type [] Interfaces ;
foreach(Type CurrentType in AssemblyTypes) {
object [] attributes = CurrentType.GetCustomAttributes(false);
foreach(object CurAttr in attributes) {
if(CurAttr is PluginAttribute) {
Console.WriteLine("Found plugin " + CurrentType.FullName);
Console.WriteLine(((PluginAttribute)CurAttr).Name +
((PluginAttribute)CurAttr).Description);
Interfaces = CurrentType.GetInterfaces() ;
foreach(Type foo in Interfaces) {
Console.WriteLine("Interface of " + foo.ToString());
}
PluginEntry p = new PluginEntry();
p.AssemblyPath = _AssemblyPath ;
p.Type = CurrentType ;
p.Interfaces = Interfaces ;
//at this point we have all the info add it
PluginEntries.Add(p) ;
break;
}
}
}
Console.Write("Loaded " + AssemblyTypes.Length + " objects.\n");
}

Once you have the types you would just use CreateInstance to create them.

I would also recommend using an optional custom attribute on your plugins so
you can optionally give them a friendlyname, description, etc.

Example:

[AttributeUsage(AttributeTargets.Class,Inherited=fa lse,AllowMultiple=false)]
public class PluginAttribute : Attribute {
private string m_Name;
private string m_Description;

public PluginAttribute(string _Name, string _Description) {
this.m_Name = _Name ;
this.m_Description = _Description ;
}

public string Name {
get {
return m_Name;
}
}

public string Description {
get {
return m_Description;
}
}
}

Maintaining plugins in a seperate app domain has benefits but complicates
things a bit. Let me know if you need info on that.

Hope this helps ya a bit.

Greg

"Gary James" <ga***@iotech.com> wrote in message
news:ea**************@tk2msftngp13.phx.gbl...
This may not be a direct C# question, but since I'll be using using C# for
development, I thought I'd pose the question here.

I'll soon be involved in the design of a new software product that will
employ a software "Plug-In" architecture. Taking the plug-in route will
give us a design that can adapt to, as yet, undefined future requirements
(within the scope of the plug-in interface spec of course). In the past
I've done this with COM components that register themselves in a list of
available code resources. However, I'd be interested to hear how any of
you have approached the design for a software plug-in architecture, and/or
any references you may have used to make your design decision.

Gary ...

Nov 16 '05 #3

P: n/a

Greg,

Whew ... now that's a response!!!

To answer your questions;

(1) I envision the need for two types of plugins. TypeA would be a single
use plugin; that is, only one plugin of multiple TypeA plugins can run at a
time. An example of this would be to provide the program with multiple GUI
interfaces., each tailored for a specific niche application. The main
program would be configured to start and load the specified application
interface. The TypeB plugin would provide optional services and
functionality to the application. This model would be similar in concept to
the one employed by video codecs. The presence of the plugin means that it
can be instantiated and used alone, or in concert with others. Examples of
this would be different plugins that provide different views, or methods of
processing data. I prefer the design to be modular with only one plugin
per assembly. This would isolate code and make regression testing simpler
following maintenance cycles. Also, multiple developers can be working on
multiple plugins.

(2) The plugins will be local only. They will be released as part of a CD
software installation, with newer versions or additions available on CD or
FTP download.

If you have any other suggestions I'd really like to hear them. Thanks.

Gary ...
"Greg Young" <gr********@planetbeach.com> wrote in message
news:%2****************@TK2MSFTNGP12.phx.gbl...
doing an interface based plugin system is remarkably easy ...

a few questions though...

1) do you want to isolate the plugins ? i.e. seperate appdomains
2) are the plugins to be local or do they need to be capable of being
distributed objects ?

the simplest route for plugins providing you don't want either of the above is just to run through an assembly getting the types ... you can then run
through the interfaces that the type supports .. supporting inheritance
chains as well is not very difficult. You would then up with a factory
method that you pass in a type to ... it would return the objects in the
assemblies you told it to look in (i.e. a subdirectory). You could also
strongly type these factories by subclassing specific plugin factories ... I would also recommend lazy loading this info and hitting a cache the second
time through as it can be slow to get this info (esp with debug symbols).

slightly modified example (only loads plugins with attribute but loads them for all interfaces they support) ...

public void LoadAssembly(string _AssemblyPath) {
Assembly PluginAssembly;
try {
PluginAssembly = Assembly.LoadFrom(_AssemblyPath) ;
}
catch (Exception Ex) {
throw new System.Exception("Unable to load assembly " + _AssemblyPath,
Ex) ;
}
//have assembly get all types.
System.Type [] AssemblyTypes = PluginAssembly.GetTypes() ;
Type [] Interfaces ;
foreach(Type CurrentType in AssemblyTypes) {
object [] attributes = CurrentType.GetCustomAttributes(false);
foreach(object CurAttr in attributes) {
if(CurAttr is PluginAttribute) {
Console.WriteLine("Found plugin " + CurrentType.FullName);
Console.WriteLine(((PluginAttribute)CurAttr).Name +
((PluginAttribute)CurAttr).Description);
Interfaces = CurrentType.GetInterfaces() ;
foreach(Type foo in Interfaces) {
Console.WriteLine("Interface of " + foo.ToString());
}
PluginEntry p = new PluginEntry();
p.AssemblyPath = _AssemblyPath ;
p.Type = CurrentType ;
p.Interfaces = Interfaces ;
//at this point we have all the info add it
PluginEntries.Add(p) ;
break;
}
}
}
Console.Write("Loaded " + AssemblyTypes.Length + " objects.\n");
}

Once you have the types you would just use CreateInstance to create them.

I would also recommend using an optional custom attribute on your plugins so you can optionally give them a friendlyname, description, etc.

Example:

[AttributeUsage(AttributeTargets.Class,Inherited=fa lse,AllowMultiple=false)] public class PluginAttribute : Attribute {
private string m_Name;
private string m_Description;

public PluginAttribute(string _Name, string _Description) {
this.m_Name = _Name ;
this.m_Description = _Description ;
}

public string Name {
get {
return m_Name;
}
}

public string Description {
get {
return m_Description;
}
}
}

Maintaining plugins in a seperate app domain has benefits but complicates
things a bit. Let me know if you need info on that.

Hope this helps ya a bit.

Greg

"Gary James" <ga***@iotech.com> wrote in message
news:ea**************@tk2msftngp13.phx.gbl...
This may not be a direct C# question, but since I'll be using using C# for development, I thought I'd pose the question here.

I'll soon be involved in the design of a new software product that will
employ a software "Plug-In" architecture. Taking the plug-in route will give us a design that can adapt to, as yet, undefined future requirements (within the scope of the plug-in interface spec of course). In the past I've done this with COM components that register themselves in a list of
available code resources. However, I'd be interested to hear how any of you have approached the design for a software plug-in architecture, and/or any references you may have used to make your design decision.

Gary ...



Nov 16 '05 #4

P: n/a
Ok no problem ... In the attribute I gave you I would define the role of the
plugin (multiple vs single) this would allow you to key off it in your
generic factory (you could also force it to be a singleton if you saw fit).
For interface type things you could even define them via plugin name in your
config file (i.e. friendly names instead of class names).

Make sure to put your interfaces / plugin required data types in a separate
assembly (this way 3rd parties can just reference this .dll instead of your
actual assemblies). Another benefit of this is your public contracts to the
plugins are all isolated making it much easier to maintain.

For maintaining plugins (loading etc) the methodology I use now is to put
them in a directory tree ... Then I call a function like ...

#region LoadPluginDirectoryTree

public void LoadPluginDirectoryTree(string _Path) {

if(!System.IO.Directory.Exists(_Path)) {

throw new System.IO.DirectoryNotFoundException("Source folder '" + _Path +
"' not found");

}

try {

string [] DirList = System.IO.Directory.GetDirectories(_Path);

foreach(string DirEntry in DirList) {

LoadPluginDirectoryTree(DirEntry) ;

}

string [] FileList = System.IO.Directory.GetFiles(_Path);

foreach(string CurrentFile in FileList) {

try {

this.LoadAssembly(CurrentFile) ;

}

catch (Exception Ex) {

//we should raise an event some day

throw Ex;

}

}

}

catch(Exception Ex) {

throw Ex;

}

}

#endregion

This will recurse through the directory tree loading the assemblies ... This
is an "unlazy" load which can take a few seconds but because I am building
up indexes for the types inside of loadassembly it is lightening fast for
retrieval.

Hope this helps you out,

Greg

-----Original Message-----

From: Gary James [mailto:ga***@iotech.com]

Sent: Friday, June 18, 2004 1:50 PM

To: Greg Young

Subject: Re: References for designing a "Plug-In" software architecture

Greg,

Whew ... now that's a response!!!

To answer your questions;

(1) I envision the need for two types of plugins. TypeA would be a single
use plugin; that is, only one plugin of multiple TypeA plugins can run at a
time. An example of this would be to provide the program with multiple GUI
interfaces., each tailored for a specific niche application. The main
program would be configured to start and load the specified application

interface. The TypeB plugin would provide optional services and

functionality to the application. This model would be similar in concept to
the one employed by video codecs. The presence of the plugin means that it

can be instantiated and used alone, or in concert with others. Examples of

this would be different plugins that provide different views, or methods of

processing data. I prefer the design to be modular with only one plugin

per assembly. This would isolate code and make regression testing simpler

following maintenance cycles. Also, multiple developers can be working on

multiple plugins.

(2) The plugins will be local only. They will be released as part of a CD

software installation, with newer versions or additions available on CD or
FTP download.

If you have any other suggestions I'd really like to hear them. Thanks.

Gary ...

"Greg Young" <gr********@planetbeach.com> wrote in message
news:%2****************@TK2MSFTNGP12.phx.gbl...
doing an interface based plugin system is remarkably easy ... a few questions though... 1) do you want to isolate the plugins ? i.e. seperate appdomains 2) are the plugins to be local or do they need to be capable of being distributed objects ? the simplest route for plugins providing you don't want either of the
above
is just to run through an assembly getting the types ... you can then run through the interfaces that the type supports .. supporting inheritance chains as well is not very difficult. You would then up with a factory method that you pass in a type to ... it would return the objects in the assemblies you told it to look in (i.e. a subdirectory). You could also strongly type these factories by subclassing specific plugin factories ...
I
would also recommend lazy loading this info and hitting a cache the second time through as it can be slow to get this info (esp with debug symbols). slightly modified example (only loads plugins with attribute but loads
them
for all interfaces they support) ... public void LoadAssembly(string _AssemblyPath) { Assembly PluginAssembly; try { PluginAssembly = Assembly.LoadFrom(_AssemblyPath) ; } catch (Exception Ex) { throw new System.Exception("Unable to load assembly " + _AssemblyPath, Ex) ; } //have assembly get all types. System.Type [] AssemblyTypes = PluginAssembly.GetTypes() ; Type [] Interfaces ; foreach(Type CurrentType in AssemblyTypes) { object [] attributes = CurrentType.GetCustomAttributes(false); foreach(object CurAttr in attributes) { if(CurAttr is PluginAttribute) { Console.WriteLine("Found plugin " + CurrentType.FullName); Console.WriteLine(((PluginAttribute)CurAttr).Name + ((PluginAttribute)CurAttr).Description); Interfaces = CurrentType.GetInterfaces() ; foreach(Type foo in Interfaces) { Console.WriteLine("Interface of " + foo.ToString()); } PluginEntry p = new PluginEntry(); p.AssemblyPath = _AssemblyPath ; p.Type = CurrentType ; p.Interfaces = Interfaces ; //at this point we have all the info add it PluginEntries.Add(p) ; break; } } } Console.Write("Loaded " + AssemblyTypes.Length + " objects.\n"); } Once you have the types you would just use CreateInstance to create them. I would also recommend using an optional custom attribute on your plugins
so
you can optionally give them a friendlyname, description, etc. Example:
[AttributeUsage(AttributeTargets.Class,Inherited=fa lse,AllowMultiple=false)]
public class PluginAttribute : Attribute { private string m_Name; private string m_Description; public PluginAttribute(string _Name, string _Description) { this.m_Name = _Name ; this.m_Description = _Description ; } public string Name { get { return m_Name; } } public string Description { get { return m_Description; } } } Maintaining plugins in a seperate app domain has benefits but complicates things a bit. Let me know if you need info on that. Hope this helps ya a bit. Greg "Gary James" <ga***@iotech.com> wrote in message news:ea**************@tk2msftngp13.phx.gbl...
This may not be a direct C# question, but since I'll be using using
C#
for
development, I thought I'd pose the question here. I'll soon be involved in the design of a new software product that will employ a software "Plug-In" architecture. Taking the plug-in route
will
give us a design that can adapt to, as yet, undefined future
requirements
(within the scope of the plug-in interface spec of course). In the
past
I've done this with COM components that register themselves in a list of available code resources. However, I'd be interested to hear how any
of
you have approached the design for a software plug-in architecture,
and/or
any references you may have used to make your design decision. Gary ...
"Gary James" <ga***@iotech.com> wrote in message
news:eu**************@TK2MSFTNGP09.phx.gbl...
Greg,

Whew ... now that's a response!!!

To answer your questions;

(1) I envision the need for two types of plugins. TypeA would be a single
use plugin; that is, only one plugin of multiple TypeA plugins can run at a time. An example of this would be to provide the program with multiple GUI interfaces., each tailored for a specific niche application. The main
program would be configured to start and load the specified application
interface. The TypeB plugin would provide optional services and
functionality to the application. This model would be similar in concept to the one employed by video codecs. The presence of the plugin means that it can be instantiated and used alone, or in concert with others. Examples of this would be different plugins that provide different views, or methods of processing data. I prefer the design to be modular with only one plugin
per assembly. This would isolate code and make regression testing simpler following maintenance cycles. Also, multiple developers can be working on multiple plugins.

(2) The plugins will be local only. They will be released as part of a CD software installation, with newer versions or additions available on CD or
FTP download.

If you have any other suggestions I'd really like to hear them. Thanks.

Gary ...
"Greg Young" <gr********@planetbeach.com> wrote in message
news:%2****************@TK2MSFTNGP12.phx.gbl...
doing an interface based plugin system is remarkably easy ...

a few questions though...

1) do you want to isolate the plugins ? i.e. seperate appdomains
2) are the plugins to be local or do they need to be capable of being
distributed objects ?

the simplest route for plugins providing you don't want either of the above
is just to run through an assembly getting the types ... you can then

run through the interfaces that the type supports .. supporting inheritance
chains as well is not very difficult. You would then up with a factory
method that you pass in a type to ... it would return the objects in the
assemblies you told it to look in (i.e. a subdirectory). You could also
strongly type these factories by subclassing specific plugin factories .... I
would also recommend lazy loading this info and hitting a cache the
second time through as it can be slow to get this info (esp with debug symbols).
slightly modified example (only loads plugins with attribute but loads

them
for all interfaces they support) ...

public void LoadAssembly(string _AssemblyPath) {
Assembly PluginAssembly;
try {
PluginAssembly = Assembly.LoadFrom(_AssemblyPath) ;
}
catch (Exception Ex) {
throw new System.Exception("Unable to load assembly " + _AssemblyPath, Ex) ;
}
//have assembly get all types.
System.Type [] AssemblyTypes = PluginAssembly.GetTypes() ;
Type [] Interfaces ;
foreach(Type CurrentType in AssemblyTypes) {
object [] attributes = CurrentType.GetCustomAttributes(false);
foreach(object CurAttr in attributes) {
if(CurAttr is PluginAttribute) {
Console.WriteLine("Found plugin " + CurrentType.FullName);
Console.WriteLine(((PluginAttribute)CurAttr).Name +
((PluginAttribute)CurAttr).Description);
Interfaces = CurrentType.GetInterfaces() ;
foreach(Type foo in Interfaces) {
Console.WriteLine("Interface of " + foo.ToString());
}
PluginEntry p = new PluginEntry();
p.AssemblyPath = _AssemblyPath ;
p.Type = CurrentType ;
p.Interfaces = Interfaces ;
//at this point we have all the info add it
PluginEntries.Add(p) ;
break;
}
}
}
Console.Write("Loaded " + AssemblyTypes.Length + " objects.\n");
}

Once you have the types you would just use CreateInstance to create them.
I would also recommend using an optional custom attribute on your plugins so
you can optionally give them a friendlyname, description, etc.

Example:

[AttributeUsage(AttributeTargets.Class,Inherited=fa lse,AllowMultiple=false

)] public class PluginAttribute : Attribute {
private string m_Name;
private string m_Description;

public PluginAttribute(string _Name, string _Description) {
this.m_Name = _Name ;
this.m_Description = _Description ;
}

public string Name {
get {
return m_Name;
}
}

public string Description {
get {
return m_Description;
}
}
}

Maintaining plugins in a seperate app domain has benefits but complicates things a bit. Let me know if you need info on that.

Hope this helps ya a bit.

Greg

"Gary James" <ga***@iotech.com> wrote in message
news:ea**************@tk2msftngp13.phx.gbl...
This may not be a direct C# question, but since I'll be using using C#

for development, I thought I'd pose the question here.

I'll soon be involved in the design of a new software product that will employ a software "Plug-In" architecture. Taking the plug-in route will give us a design that can adapt to, as yet, undefined future requirements (within the scope of the plug-in interface spec of course). In the past I've done this with COM components that register themselves in a list of available code resources. However, I'd be interested to hear how any of you have approached the design for a software plug-in architecture, and/or any references you may have used to make your design decision.

Gary ...


Nov 16 '05 #5

P: n/a
Gary... Easy enough to do, but you may want to design in some type of
verification policy for loading untrusted plugins.

http://www.geocities.com/jeff_louie/OOP/oop13.htm

Regards,
Jeff

*** Sent via Devdex http://www.devdex.com ***
Don't just participate in USENET...get rewarded for it!
Nov 16 '05 #6

P: n/a
Interesting read. Thanks for the tip Jeff.
"Jeff Louie" <je********@yahoo.com> wrote in message
news:%2****************@TK2MSFTNGP11.phx.gbl...
Gary... Easy enough to do, but you may want to design in some type of
verification policy for loading untrusted plugins.

http://www.geocities.com/jeff_louie/OOP/oop13.htm

Regards,
Jeff

*** Sent via Devdex http://www.devdex.com ***
Don't just participate in USENET...get rewarded for it!


Nov 16 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.