|
The source of SourceForge has an example application in it, so that helped.
The only other example I know of is a GitHub (because of course it is), here[^]
How about this to get you started:
First, the pluggable application.
1. Open your pluggable application project in Visual Studio.
2. Add a reference to the SimplePlugins.dll from your project.
3. Add using/imports directives where you would like to initialize and use the plugin loader provided by the library like so,
using SimplePlugins;
using SimplePlugins.Exceptions;
4. Initialize the PluginLoader object like so,
this.PluginLoader = new PluginLoader();
5. You can specify additional paths where plugin dependencies will be located like so,
this.PluginLoader.AssemblyResolutionPaths.Add(Application.StartupPath);
6. You can make the plugin loader use the .Net framework’s shadow copy option when loading assemblies like so, (You can further customize the cache path, etc by handling the PluginLoader.PluginLoading event)
this.PluginLoader.ShadowCopyEnabled = true;
7. You can then hook up to the several events which enable the pluggable application to manage plugin behavior like so,
this.PluginLoader.ProbeComplete += new PluginLoaderBase.ProbeCompleteEventHandler(PluginLoader_ProbeComplete);
this.PluginLoader.PluginLoading += new PluginLoaderBase.PluginLoadingEventHandler(PluginLoader_PluginLoading);
this.PluginLoader.PluginLoaded += new PluginLoaderBase.PluginLoadedEventHandler(PluginLoader_PluginLoaded);
this.PluginLoader.PluginUnloaded += new PluginLoaderBase.PluginUnloadedEventHandler(PluginLoader_PluginUnloaded);
8. You can probe available plugins from a location in the hard disk as follows, The PluginLoader.Probe method scans the specified directory and subdirectories for valid plugin assemblies and returns a list.
PluginInfoList pluginInfoList = this.PluginLoader.Probe("C:\plugins", SearchOption.AllDirectories);
for (int i = 0; i < pluginInfoList.Count; i++)
lbPlugins.Items.Add(pluginInfoList[i]);
9. Use the PluginLoader.Load method to execute any of the plugins returned by the PluginLoader.Probe method above. Parameters can also be passed to the plugin using the PluginParameters class. Any unhandled exceptions which may occur during the loading process is wrapped by the serializable PluginException class and rethrown to make sure no AppDomain leakages occur. Hence the try-catch block.
PluginInfo template = (PluginInfo)lbPlugins.SelectedItem;
try
{
PluginParameters args = new PluginParameters();
args.Add("Param1", "The quick brown fox jumped over the lazy dog");
args.Add("Param2", 100);
args.Add("Param3", 7.321);
this.PluginLoader.Load(template.FileName, args);
}
catch (PluginException ex)
{
Console.WriteException(ex);
}
10. You may use the PluginLoader.NotifyUnload or PluginLoader.NotifyUnloadAll methods to notify a plugin that it needs to be unloaded.
11. You can use the PluginLoader.PluginUnloaded event to check whether plugins executed successfully and their return values as follows.
void PluginLoader_PluginUnloaded(object sender, PluginLoaderBase.PluginUnloadedEventArgs e)
{
if (e.Results.UnhandledException != null)
Console.WriteException("The plugin '" + e.Info.ToString() + "' was unloaded due to unhandled exception: " + e.Results.UnhandledException.ToString());
else if (e.Results.ExecutionDenied)
{
if (e.Info.ExecutionMode == PluginBase.ExecutionModes.AsynchronousExclusive || e.Info.ExecutionMode == PluginBase.ExecutionModes.SynchronousExclusive)
Console.WriteInfo("The plugin '" + e.Info.ToString() + "' was unloaded since it is intended to be executed exclusively. Please make sure no other plugin is executing and try again.");
else if (e.Info.ExecutionMode == PluginBase.ExecutionModes.AsynchronousSingleton || e.Info.ExecutionMode == PluginBase.ExecutionModes.SynchronousSingleton)
Console.WriteInfo("The plugin '" + e.Info.ToString() + "' was unloaded since only one instance of it is intended to be executed at a time. Please make sure no other instance of the same plugin is executing and try again.");
else
Console.WriteInfo("The plugin '" + e.Info.ToString() + "' was unloaded.");
}
else
{
if (e.Results.Contains("ReturnValue"))
Console.WriteInfo("The plugin '" + e.Info.ToString() + "' was unloaded successfully with the return value: " + Convert.ToString(e.Results.Get("ReturnValue")));
else
Console.WriteInfo("The plugin '" + e.Info.ToString() + "' was unloaded successfully");
}
}
That’s it! You have got yourself a pluggable application. Now you can write a plugin by following the steps below.
1. Open or create a project for the plugin in Visual Studio. This can be an executable type project or a class library project.
2. Add a reference to the SimplePlugins.dll.
3. Add a class under any name which will represent the plugin. Derive this class from the PluginBase abstract class provided by the Simple Plugins library and override its methods appropriately. Place your main processing code inside the Main method. The Main method is called by the PluginLoader.Load method after the plugin is successfully loaded.
using SimplePlugins;
using SimplePlugins.Exceptions;
namespace SamplePluggableApp.SamplePlugin
{
public class Plugin : PluginBase
{
public Plugin()
: base()
{
}
internal string Param1 { get; private set; }
internal int Param2 { get; private set; }
internal double Param3 { get; private set; }
public override string FriendlyName
{
get { return "Sample Plugin"; }
}
public override ExecutionModes ExecutionMode
{
get { return ExecutionModes.AsynchronousMultiInstance; }
}
public override PluginParameters Main(PluginParameters args)
{
this.Param1 = (string)args.Get("Param1");
this.Param2 = (int)args.Get("Param2");
this.Param3 = (double)args.Get("Param3");
MainView pluginForm = new MainView();
pluginForm.Show();
Application.Run(pluginForm);
args.Add("ReturnValue", "Success");
return args;
}
public override void OnUnloadNotification()
{
Application.Exit();
}
}
}
That’s all there is to it. Place the output of your plugin project in the plugins folder path and let Simple Plugins do everything else for you. If the functionality provided by the standard PluginLoader and PluginBase classes are not enough, you can extend those classes to meet your own needs. You may refer the code on how the default PluginLoader class is implemented to get an idea about writing a custom loader.
|
|
|
|
|
thanks for that.
".45 ACP - because shooting twice is just silly" - JSOP, 2010
- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010
- When you pry the gun from my cold dead hands, be careful - the barrel will be very hot. - JSOP, 2013
|
|
|
|
|
Well, that didn't do me a lot of good. I still have to go home and unblock the dll (or bring the source code to work) because our group policy doesn't allow us to unblock a remote dll.
I hate where I work...
I'm off to do other crap...
".45 ACP - because shooting twice is just silly" - JSOP, 2010
- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010
- When you pry the gun from my cold dead hands, be careful - the barrel will be very hot. - JSOP, 2013
|
|
|
|
|
Well, I can't do anything about that. Sorry.
|
|
|
|
|
Just write something that is so complex they have to cart you off to the funny farm...just for sh*ts and giggles of course.
Stop talking to me, I'm not talking to you, then who is talking to me. Why won't the voices stop!
|
|
|
|
|
Visual Studio 2015 is totally MEF based, 2012 and 2013 is as well, I think. Just saying... For good or bad
|
|
|
|
|
I'm gonna pray for those around you.
|
|
|
|
|
"Maf" is actually the Dutch word for "weird"
|
|
|
|
|
Given the sheer amount of guns and ammo you do possess, I pray for those around you.
|
|
|
|
|
If a chicken crosses the road, is that poultry in motion?
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
|
|
|
|
|
Bootiful!
I wanna be a eunuchs developer! Pass me a bread knife!
|
|
|
|
|
|
Just as long as it stays abreast of the oncoming Mac truck!
Marc
|
|
|
|
|
It's Big that truck - thank you for that Nugget of information!
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
|
|
|
|
|
Feather you realize it or not, that's a lot of crop to peck through and consider.
Ravings en masse^ |
---|
"The difference between genius and stupidity is that genius has its limits." - Albert Einstein | "If you are searching for perfection in others, then you seek disappointment. If you are seek perfection in yourself, then you will find failure." - Balboos HaGadol Mar 2010 |
|
|
|
|
|
I want to live in a world where a chicken can cross the road without its motives being questioned.
|
|
|
|
|
it's a free chicken
|
|
|
|
|
You get a good one, so are you going to crow about it.
Mongo: Mongo only pawn... in game of life.
|
|
|
|
|
Nah - you'll just flip me the bird if I do!
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
|
|
|
|
|
Reminds me of the children's poem:
Birdy, birdy, in the sky, why'd you do that in my eye, gee I'm glad cows can't fly.
Mongo: Mongo only pawn... in game of life.
|
|
|
|
|
Mary had a little lamb,
She also had a duck.
She put them on the mantlepiece,
To see if they would f...all off.
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
|
|
|
|
|
Mary had a little lamb,
The doctor was surprised.
When old MacDonald had a farm,
The old quack nearly died!
If you have an important point to make, don't try to be subtle or clever. Use a pile driver. Hit the point once. Then come back and hit it again. Then hit it a third time - a tremendous whack.
--Winston Churchill
|
|
|
|
|
Dost thou imply that, of a walking hen,
Across the road it travels, to only then
Meet up with a Roost, he being quite the C0ck,
Who takes the same upon the hen behind the hardened rock?
|
|
|
|
|
|
This is a story of self-control and marksmanship by a brave, cool-headed woman with a walking stick against a fierce predator.
Here is her story in her own words:
"While out walking along the edge of a creek just outside of our house in Darwin with my soon to be ex-husband discussing our property settlement, kids and other divorce issues, we were surprised by a huge 5 metre. Crocodile which suddenly emerged from the murky water and began charging at us very fast with its large jaws wide open.
The Croc must have been protecting her young and her home because she was extremely aggressive. If I had not had my little $5 Reject Shop walking stick with me, I would not be here today!
Just one hard whack to my estranged husband's knee cap was all it took.. ..The Croc got him easily and I was able to escape by just walking away at a brisk pace.
The amount I saved in lawyer’s fees was really incredible and I got the lot.
|
|
|
|