473,395 Members | 2,796 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

References for designing a "Plug-In" software architecture

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
6 2920
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
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

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
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
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
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

35
by: Will Stuyvesant | last post by:
Here is a question about list comprehensions . The question is dumb because I can do without ; but I am posing the question because I am curious. This: >>> data = ,,] >>> result = >>> for...
2
by: Loane Sharp | last post by:
Hi there I'm using VB.NET and Office Web Components to access a SQL Server 2005 Express database and draw pictures on the fly in my ASP.NET application. Using .ExportPicture to write the...
42
by: Martin Jørgensen | last post by:
Hi, I'm trying to move a matlab program into c language. For those who knows matlab, this is the line I want to program in c: hx(1:nx,1:ny) = 0; % nx=10, ny=10 It works on a 2-dimensional...
4
by: Johndow | last post by:
I have trouble to use "Is" operator to a type that is from reflection. Basically, here is what I want to do, if Class1 type is not from reflection: class Class1 { } public class Test { ... if...
7
by: spinoza1111 | last post by:
"segfault city" was an interchange wherein Richard Heathfield posted a complete lie: <heathfield> Richard Heathfield wrote: > This would be a straightforward test for numerics: > > int...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.