My application allows users to write plugins (implementing IPlugin) that they can instantiate at runtime. On startup a directory of plugin .dlls is parsed, registering all the available plugins information. At runtime a GUI is provided that lets users create instances of any of the plugins. This works fine.
But now I see MEF and hope I can do the same, but in a more elegant way codewise.
What I got working so far with MEF: on startup I am doing an import of all plugins in a directory (that export IPlugin) and read out the information like name, category, author, etc... These are encoded as exported metadata attributes to the plugin classes. The import is done lazyly so all the plugins are not instantiated on startup, which is important.
The problem is that now I don't see a way to elegantly instantiate a selected plugin at runtime given the additional complication that the plugins constructor is an importing constructor which is importing a reference to an IPluginHost (which it needs immediately to do some initialization).
Together with a plugininfo I save the respective Export in a dictionary during startup, so when the GUI asks to instantiate a plugin given a specific plugininfo I have access to the Export (where Export.Value is my actual IPlugin). But from there how can I create an instance of the plugin and have it composed with the IPluginHost?
I gather I should write my own ExportProvider that serves the IPluginHost whenever someone asks for it, but I don't have access to the assembly or the type of the specific plugin that would let me add it to a Catalog, add the catalog and ExportProvider to a container and call .ComposeParts on that container.
I hope I made my problem clear, if not, let me try a short version of the question:
isn't it a standard usecase for MEF to have a program that lazy-loads plugins on startup to parse the available plugins infos and then at runtime create specific instances given specific plugininfos? would be great to get a codeoutline of the steps involved.
If I understand correctly, you are looking for a way to dynamically create multiple plugin instances, potentially of the same plugin.
You need to declare an import of the type ExportFactory<IPlugin,IPluginMetadata> and then select the correct factory based on the metadata. ExportFactory.CreateExport will take care of any imports required by the IPlugin instances, like the IPluginHost you mentioned.
Note that ExportFactory was only in the silverlight edition of MEF in earlier releases. To get it in the desktop edition, you currently need the latest version from codeplex (MEF 2 - Preview 1). There is also a known problem with importing ExportFactory via the constructor, so use a property.
Have you created a CompositionContainer yet? You can use it to request particular plugin types and get them instantiated. The catalogs will get you part of the way there. You can aggregate multiple catalogs (using the AggregateCatalog) then pass the result to the constructor of the CompositionContainer. When you request your specific IPlugin Type (just keep track of the Type of the export) and you can ask the CompositionContainer to instantiate the plugin for you and it will do the constructor injection for you automatically.
Related
I have a ASP.NET MVC application and a plugin that needs to write to the web.config file. For various reasons, I've found that the most appropriate way to do this is during compilation using MSBuild configuration, so I have created an executable distributed with my plugin to be called here with appropriate parameters for resolving consumer-application dependencies like the path to the config file.
The plugin is configurable, and the definition for this must be in the consumer application in a specific class.
Now the plugin-executable has to be able to read this class, but we can not have any hard-coded dependencies since the plugin should be distributable and used in many different applications.
I have found this answer here on SO about dynamically loading/unloading DLLs, and my question is if this is the approach to use, while passing in the relevant parameters as arguments to the exe, or do I have any other options?
The answer is Yes but you can do it in two different ways.
If you want to unload the class yes you need to create a new AppDomain, use it and unload it in the end, to do this you need a class that implements MarshalByRefObject it's much more complicated.
If the class can live during the lifetime of the client application you just need to load your plugin to the current AppDomain.
AppDomain.CurrentDomain.CreateInstanceAndUnwrap(assemblyName, typeName);
I strongly recommend that the instance you are loading implements a specific Interface so you can inspect a folder for DLL's like this
var ass = Assembly.LoadFrom(path);
ass.DefinedTypes.Where(t => t.ImplementedInterfaces
.Any(i => i.AssemblyQualifiedName ==
typeof(<Defined Interface>).AssemblyQualifiedName))
this will return a list of types that implement your interface so you just need to use the above code to create one instance.
I think that to work with msbuild you need to take the first approach and do all the load unload and usage inside of the class that implements MarshalByRefObject don't quote me on this one.
Sorry if I am not clear enough, I've had a hard time writing this question.
I downloaded an open source software. I would like to expand the functionalities so I would like to create modules that encapsulates the functionality these modules would be .dll files.
I would like to have one completely independent from another: if I set a key to true in the config file and if the DLL is present on the folder, the plugin should be loaded.
The problem is: how can I make the call for the plugin dynamically (only call of the plugin is applied)?
If I reference the plugin classes directly, I would have to reference the plugin dll, but I want to be able to run the core software without the plugin. Is there any design pattern or other mechanism that would allow me to load and use the DLL only if the plugin is applied and still be possible to run the core software without the plugin?
There are various ways to achieve this and I will describe one simple solution here.
Make a common interface that each plugin must implement in order to be integrated with core application. Here is an example:
// Interface which plugins must implement
public interface IPlugin
{
void DoSomething(int Data);
}
// Custom plugin which implements interface
public class Plugin : IPlugin
{
public void DoSomething(int Data)
{
// Do something
}
}
To actually load your plugin from dll, you will need to use reflection, for example:
// Load plugin dll and create plugin instance
var a = Assembly.LoadFrom("MyCustomPlugin.dll");
var t = a.GetType("MyCustomPlugin.Plugin");
var p = (IPlugin)Activator.CreateInstance(t);
// Use plugin instance later
p.DoSomething(123);
You can use some kind of naming convention for your plugin assemblies and classes
so that you can load them easily.
You can use MEF.
The Managed Extensibility Framework (MEF) is a composition layer for
.NET that improves the flexibility, maintainability and testability of
large applications. MEF can be used for third-party plugin
extensibility, or it can bring the benefits of a loosely-coupled
plugin-like architecture to regular applications.
Here is programming guide.
Plugins or DLLs in .NET jargon are called assemblies. Check out the Assemply.Load method, and also this guide in msdn.
The System.Reflection namespace provides many tools that will help you with this scenario.
You can
inspect assemblies (DLL files) to examine the objects inside them,
find the types that you are looking for (specific classes, classes which implement specific interfaces, etc)
create new instances of those classes, and
invoke methods and access properties of those classes.
Typically you would write a class in the extension which does some work, create a method (e.g. DoWork()), and then invoke that method dynamically.
The MEF mentioned in this question does exactly this, just with a lot more framework.
Not sure the exact terms to use here, so any help would be appreciated.
To be the most simplistic, I have a forms application. When I load "form.exe", the form has one control, a menu. This menu has one menuitem, "Exit". What I would like, is when the Form is loading, be able to pass in arguments to this forms app that specify DLLs that could add specialized methods, controls, etc.
Now when I load "form.exe add_plugable.dll", my menu has another menuitem, "Add".
When I load "form.exe add_plugable.dll remove_pluggable.dll", menu has 3 items "Exit", "Add", and "Remove".
Hope this makes sense. What do I need to include in the Forms application and how do I create my DLLs? I am aware I need a common interface, but dont know exactly how to accomplish this with namespaces and interfaces and abstract classes.
Thanks!
I would recommend looking into the Managed Extensibility Framework. It was designed for this exact type of scenario.
For example, it is what Visual Studio uses for its extensibility, so add ins can be dynamically discovered and plugged in at runtime.
You can use a pre-written framework, but if you are looking for a "bare bones" solution, try this:
Create an interface (or set of interfaces, if you prefer) that contains all methods that the forms app will call, e.g. IPlugin. Put the interface(s) in a separate class library.
In each plugin DLL, create a public class that implements IPlugin.
In the forms app, decide what plugins to load and when to call them. This logic is entirely up to you.
Load a plugin like this, then call the interface members to accomplish what you want. You could read the plugin file and class names from app.config, a database, or calculate them via a naming convention, according to your requirements.
var pluginAssembly = Assembly.Load(pluginFileName);
var plugin = (IPlugin) pluginAssembly.CreateInstance(pluginClassName);
These methods have several overloads allowing more control over the process. For example, you can load the plugin assembly using an AssemblyName rather than a simple string. When instantiating the class, you can specify binding flags and a set of parameter values to pass to the class's constructor.
I'd like to build an infrastructure that will monitor a server and check ping, response time, and more.
The catch is that future checks (for example: does a certain file exist) will be added without recompiling the infrastructure.
How do I build it in such a way that will enable me to attach inherited classes with different functionality, and execute them without recompiling?
Thanks!
In addition to creating an interface and defining a single entry point for your new library, you could create an attribute which identifies the classes that you need to load or the methods that you need to call. You then use reflection to look at all the DLLs in a certain path, and instantiate / run whatever contains your attribute.
I've built a similar application that had to perform a number of health checks on a system, and needed to be extensible. The application started, looked through all the DLLs in a specified path and for each class with the 'TestAttribute' decoration it would create an instance and run the 'Execute' method.
The use of an attribute means that you don't need to specify which DLLs to process (doesn't need to be in config / database) because it's safe to process every DLL, and only those decorated with the attribute will do anything.
Implement an interface, and the provider pattern, then you can plug anything in that you like. MSBuild is a great example of this, with a simple interface you can add any type of task you like to your build process - follow the same sort of pattern.
Sounds like you could use some kind of 'plugin' mechanism. Define a basic interface and you can compile every "check/action" into a separate assembly. Load all your assemblies dynamically from file and call execute the check/action via the defined interface.
The interface could be just as simple as this, for starters:
public interface IMonitorAction
{
bool Exectute();
}
This infrastructure allows you to add more checks by just creating another assembly file implementing the interface next to the existing ones.
Of the top of my head.
I presume you can re-start you application.
Have a file that lists all the DLL's to load that implement your required functionality. Each DLL should have the same name entry point. Load each DLL, call the method, unload DLL. loop.
Caveat: I've never done anything like this, so I may be talking hot air.
Adding to #slugsters answer, instead of building your own extensibility infrastructure, take a look at extensibility libraries like MEF.
I've had a few questions about MEF recently, but here's the big one -- is it really all-or-nothing, as it appears to be?
My basic application structure is simply an app, several shared libraries that are intended to be singletons, and several different plugins (which may implement different interfaces). The app loads the plugins, and both the app and all plugins need to access the shared libraries.
My first go at MEF was fairly successful, although I made some stupid mistakes along the way because I was trying so many different things, I just got confused at times. But in the end, last night I got my smallish test app running with MEF, some shared libraries, and one plugin.
Now I'm moving onto the target app, which I already described. And it's the multiple plugins part that has be a bit worried.
My existing application already supports multiple plugins with different interfaces by using Reflection. I need to be able to uniquely identify each plugin so that the user can select one and get the expected behavior exposed by that plugin. The problem is that I don't know how to do this yet... but that's the topic of a different question.
Ideally, I'd be able to take my existing plugin loader and use it as-is, while relying on MEF to do the shared library resolution. The problem is, I can't seem to get MEF to load them (i.e. I get a CompositionException when calling ComposeParts()) unless I also use MEF to load the plugin. And if I do this, well... then I need to know how to keep track of them as they get loaded so the user can select one from a list of plugins.
What have your experiences been with trying to mix and match these approaches?
MEF is designed to let you easily load plugin assemblies. If you have control over the plugins (by which I mean that you can add MEF export attributes) then there is no need to keep your own plugin loader which uses reflection. MEF does all that for you.
That being said, "mixing and matching" MEF with other technologies is certainly possible. It sounds like your problem is that if you use your own plugin loader, you don't add those plug-ins to the MEF container. As a result, you get a CompositionException for parts which try to import the selected plug-in.
To add a plugin that you loaded with your own code to the MEF container, you can use the ComposeExportedValue like this:
container.ComposeExportedValue<IPlugin>(selectedPlugin);
edit: I see what you mean now by "all or nothing". Your problem is that in order to be able to import parts with MEF, you also need to construct the object with MEF. This problem then cascades to the object which normally created that object, etc. all the way to the application root.
To avoid this "all or nothing" effect, you can compromise by exposing the MEF container as a global variable (i.e. static field). That way, classes can access the MEF container and pull exports from it, e.g. by calling Program.Container.GetExportedValue<MyDependency>() in the constructor.
edit2: If you have an object that was not constructed by MEF, then there are two ways to add it to the container.
The first is to call container.ComposeExportedValue<IMyContractType>(myObject);.
The second is to return the object in a property getter, and then mark the property itself with an [Export(typeof(SomeType))] attribute.