How to load third-party implementations at run-time - c#

I'm making a .Net application to manage and install mods. The application itself shouldn't be able to install mods for any particular game but should be able to call 3rd-party extensions to do so.
Let's say my mod manager expects an implementation of the given interface:
interface IGameManager {
// Deploy a modding configuration to the targeted game
void Deploy();
// Remove all managed mods from the targeted game
void Purge();
// ...
}
And someone else, working on a different code base, implement IGameManager to manage a specific game:
class MinecraftManager: IGameManager {
// ...
}
Then this person compiles it, publishes it and everyone could simply feed this extension to the main mod manager so it can manage their mods for the targeted game.
But how? Is there a way for my application to safely load and use such third-party implementations at run-time? And how to facilitate the making of third-party extension (e.g. giving an interface to build on but more elegantly and maintenance-friendly)?
Edit 1: Invalid syntax in MinecraftManager signature

You are essentially trying to design a plugin system. There are many implementations that you could reuse but the general idea is that:
You need your manager to be able to discover extensions. There are many ways to do that but the simplest and most used approach is to place extension assemblies under a well known directory in the file system. Then your manager can enumerate the assemblies in that folder by enumerating the files (or if you prefer that each extension has it own subfolder enumerate the subfolders)
Load the assembly. For that you will use one of the Assembly.Load.. methods. Since it is not possible to unload assemblies, you may want to first load the assembly for reflection only and once you decide that the assembly is valid you can load it in the ApplicationDomain in order to use it.
Use relfection to enumerate all classes of the assembly you just loaded and find the ones that implement the right interface (IGameManager). Altenatively you can require that extensions contains an "entry point" class of known name, then look for that class by name (using reflection).
Create an instance of the class(es) and use it (perhaps also keep it in a collection of loaded extensions)
Regarding the interface that extensions must implement: You should put the interface (and any other supporting interfaces) in a separate assembly. The assembly should contain only interfaces, no implementation. You can then publish the assembly. Once published the interface should never change.
If you need to add functionality you should create a new interface. This way old versions of the manager will work with newer versions of an extension (that is designed to implement the new functionality as well). Also your manager can determine which interfaces are implemented by an extension and act accordingly (thus maintaining compatibility). If the new functionality is mandatory, your manager should discard any extension that does not implement both interfaces.

I just found out dotNet 4 already have an extensibility framework (Documentations here), which is cleaner and safer than using Assembly.Load().
Here's the snippet I use to load my plugins from a given directory, if anyone encounter the same problem:
// Where T is the type you want to retrieve from the assemblies
private static IEnumerable<Lazy<T>> LoadExternalAssemblyFromPath<T>(string path, string pattern) {
CreateDirectoryIfDoesntExist(path);
AggregateCatalog catalog = new AggregateCatalog();
catalog.Catalogs.Add(new DirectoryCatalog(path, pattern));
CompositionContainer container = new CompositionContainer(catalog);
return container.GetExports<T>();
}
// Usage:
LoadExternalAssemblyFromPath("C:/path/to/plugins", "*.dll");
Regarding the implementation of such plugin, Kouvarakis' solution on the matter is correct.

Related

How to implement plugin architecture in .NET?

I have an interface in my main library. There will be multiple different implementations of this interface, those implementation will be part of different libraries, possibly distributed as nuget packages.
As per the requirement, user should be able to use a particular implementation by adding its corresponding nuget.
Providing an analogy, lets suppose I have an interface, IPizzaProvider.
public interface IPizzaProvider
{
Pizza GetMePizza(customizationParameter);
}
There will be multiple different implementations of this distributed in different NuGet packages.
DominosPizzaProvider
PizzaHutPizzaProvider
XYZPizzaProvider blah blah
Thus, these are different plugins for my main library.
Use Case:
A user adds my main library in their application.
Next, users as per their choice adds a particular nuget package (plugin) in their application.
User provides customization parameters to my main library.
Now, my library should be able to get object of Pizza through the interface without worrying about the implementation.
This will not only will help me to have loose coupling/ abstract implementation through an interface but also facilitate separate release cadence for supporting additional providers in future. I don't have to release my existing main library.
Additionally, users can also implement my interface themselves and use it with my main library.
Problem statement: How to load those DLLs in my main library and instantiate the implementation class dynamically at runtime.
One possible solution is to .NET Reflection. But then I have to scan all individual DLLs and find the assembly which contains implementation.
List<Assembly> allAssemblies = new List<Assembly>();
string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
foreach (string dll in Directory.GetFiles(path, "*.dll", SearchOption.TopDirectoryOnly))
allAssemblies.Add(Assembly.LoadFile(dll));
List<Type> providers = allAssemblies
.SelectMany(x => x.GetTypes())
.Where(t => IPizzaProvider.IsAssignableFrom(t) && t.IsClass).ToList();
There might be hundreds of DLLs at runtime path of the application and scanning them all might cause performance hit.
Is there any other possible way to implement this plugin architecture in .NET?
Java uses SPI for similar problem statement and has ServiceLoader class to load different implementation. It involves META-INF folder etc.

Instantiate plugin class in a DLL

I'm learning C# and am researching how to allow people to write plugins for an app I'm writing.
To start, I publish an API (a dll with interfaces) that their code must adhere to.
Now, I'm trying to understand how to work with their code. I've written a test plugin, built to a dll, and put it into a "plugins" directory that my script is watching.
I'm just not sure what to do next.
Since the API interfaces are shared my app knows what to expect. For example, they should have a main class which interfaces a Plugin interface.
// Example api interface:
public interface Plugin {
void Initialize();
}
// Example of their code:
public class TestPlugin : Plugin {
public void Initialize() {
// ... do stuff
}
}
My question is, how can I instantiate their TestPlugin, so that I can properly call Initialize and any other methods?
I have some ideas but am still too new to C# and don't want to jump the gun.
you need to find assemblies , load them and look for classes that implement IPlugin (please use Ixxx for interfaces)
There are helper libraries that do this for you although they feel over complex to me. MEF is the best known https://msdn.microsoft.com/en-us/library/dd460648(v=vs.110).aspx
If you want to roll your own.
Enumerate the 'plugins' directory for all .dll files
do an assembly.load on each one
enumerate the types and see if any classes supports IPLugin
if so do an activator.createinstance
good luck
The best way to do this would be to use MEF (Managed Extensibility Framework), otherwise known as the System.ComponentModel.Composition library.
If you did this, the library writer would put the following line above their class:
[Export(typeof(Plugin))]
Then you create some MEF classes to import any plugins. Start with a DirectoryCatalog since you are loading from a folder:
DirectoryCatalog pluginDir = new DirectoryCatalog("Plugins");
CompositionContainer mefContainer = new CompositionContainer(pluginDir);
Afterwards create a CompositionContainer from your catalog (shown above). Now you can have a class member marked with ImportMany like so:
[ImportMany]
private List<Plugin> plugins;
and call ComposeParts on the container, this will auto-populate your list with any exported classes found. Alternatively, you can directly ask for exports of a given type:
IEnumerable<Plugin> plugins = mefContainer.GetExportedValues<Plugin>();
One thing to note when using MEF, you get one, and only one, instance of each plugin. If you want multiple instances for some reason, have your users export a Factory.
If you want to go the hard way, you could load the assembly manually using Assembly.Load and then reflection to try and find the types implementing your interface. MEF does this work for you, so I would go with that.

How to create a loosely coupled architecture with hot-swap capability?

I'm interested in creating a desktop application composed of modules such that the source code to those modules is embedded in the application itself, allowing the user to edit the application as they are running it and have the updated modules put into use without restarting the application. Can anyone suggest a good architecture for this?
I'm looking to use Microsoft.Net and C# for this. DLR is not an option.
Thanks!
It's not easy to suggest a good architecture for this in a short posting.
At first, i'd define a contract (an Interface) every module the user writes/modifies must implement. It should contain at least an Execute method.
Then I'd create a Wrapper-Class for these modules which:
loads the source code from a file
The wrapper compiles the file and also makes sure it implements the contract
Contains an indicator of whether the file could be compiled sucessfully
It should also implement the contract, for easy calling and handling
Then I'd have some kind of shell which contains a collection of all the module-wrappers. Any wrapper that sucessfully compiled would then let the Shell call the Execute method of the module interface.
When it comes to compiling and executing code on the fly, this link should provide all the information you need:
http://www.west-wind.com/presentations/dynamicCode/DynamicCode.htm
Well, a dynamic language certainly would have been the best fit...
You can use the types in the System.Reflection.Emit namespace to dynamically create assemblies.
However, it's going to be really painful because you'd need to load those dynamic assemblies into custom AppDomains because otherwise you'll not be able to unload them again.
This again means that you must address marshalling and assembly resolution issues related to cross-AppDomain communication.
What you are probably looking for is the concept of Dependency Injection.
Dependency Injection means that instead of having module X use module Y directly, module X only relies on an interface, and the application tells module X which implementation should use for it, e.g. using module Y.
There are several ways of implementing Dependency Injection. One is to have references to the interfaces in each of your modules, and explicitly let the application configure each of its modules with the right implementation of the interface.
The second wahy of implementing it (and probably the most useful in your case) is by using a central registry. Define all the interfaces that you want to have in your application. These are the interface for which you want to dynamically change the implementation. Then define identifications for these interfaces. These could be strings or integers or GUID's.
Then make a map in your application that maps the identifications to the interfaces, and fill the map with the correct implementations of the interfaces. In a C++ application (I'm not very skilled in C# yet) this could work like this:
std::map<std::string,IInterface> appInterfaces;
appInterfaces["database"] = new OracleDatabaseModule();
appInterfaces["userinterface"] = new VistaStyleUserInterface();
Make all modules go to this central registry whenever they want to use one of the modules. Make sure they don't access the modules directly, but they only pass via the registry. E.g.
MyModule::someMethod()
{
IDatabaseInterface *dbInterface = dynamic_cast<IDatabaseInterface *>(appInterfaces["database"]);
dbInterface->executeQuery(...);
}
If you now want to change the implementation for an interface in the application, you can simply change the entry in the registry, like this:
IInterface *iface = appInterfaces["database"];
if (iface) delete iface;
appInterface["database"] = new SqlServerDatabaseInterface();

How to organize code using an optional assembly reference?

I am working on a project and want to optionally use an assembly if available. This assembly is only available on WS 2008 R2, and my ideal product whould be a common binary for both computers with and without the assembly. However, I'm primarily developing on a Windows 7 machine, where I cannot install the assembly.
How can I organize my code so that I can (with minimum changes) build my code on a machine without the assembly and secondly, how do I ensure that I call the assembly functions only when it is present.
(NOTE : The only use of the optional assembly is to instantiate a class in the library and repeatedly call a (single) function of the class, which returns a boolean. The assembly is fsrmlib, which exposes advanced file system management operations on WS08R2.)
I'm currently thinking of writing a wrapper class, which will always return true if the assembly is not present. Is this the right way to go about doing this?
My approach would be to dynamically load the assembly, instead of hard-coding a reference. Your code could then decide whether to use the assembly (if it loaded) or return some other value. If you use the assembly, you'll need to use reflection to instantiate the class and use the method. That way your code will build and run on any platform, but it's behavior will change if it detects the presence of fsrmlib.
The System.Reflection.Assembly documentation has example code for doing this.
Hide the functionality behind an interface, say:
public interface IFileSystemManager
{
void Manage(IFoo foo);
}
Create two implementations:
An implementation that wraps the desired functionality from fsrmlib
A Null Object implementation that does nothing
Inject the IFileSystemManager into your consumers using Constructor Injection:
public class Consumer
{
private readonly IFileSystemManager fileSystemManager;
public Consumer(IFileSystemManager fileSystemManager)
{
if (fileSystemManager == null)
{
throw new ArgumentNullException("fileSystemManager");
}
this.fileSystemManager = fileSystemManager;
}
// Use the file system manager...
public void Bar()
{
this.fileSystemManager.Manage(someFoo);
}
}
Make the selection of IFileSystemManager a configuration option by delegating the mapping from IFileSystemManager to concrete class to the config file so that you can change the implementation without recompiling the application.
Configure applications running on WS 2008 R2 to use the implementation that wraps fsrmlib, and configure all other applications to use the Null Object implementation.
I would recommend that you use a DI Container for the configuration part instead of rolling this functionality yourself.
Alternatively you could also consider treating the IFileSystemManager as an add-in and use MEF to wire it up for you.

Using Ninject in a plugin like architecture

I'm learning DI, and made my first project recently.
In this project I've implement the repository pattern. I have the interfaces and the concrete implementations. I wonder if is possible to build the implementation of my interfaces as "plugins", dlls that my program will load dynamically.
So the program could be improved over time without having to rebuild it, you just place the dll on the "plugins" folder, change settings and voilá!
Is this possible? Can Ninject help with this?
While Sean Chambers' solution works in the case that you control the plugins, it does not work in the case where plugins might be developed by third parties and you don't want them to have to be dependent on writing ninject modules.
This is pretty easy to do with the Conventions Extension for Ninject:
public static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Scan(scanner => {
scanner.FromAssembliesInPath(#"Path\To\Plugins");
scanner.AutoLoadModules();
scanner.WhereTypeInheritsFrom<IPlugin>();
scanner.BindWith<PluginBindingGenerator<IPlugin>>();
});
return kernel;
}
private class PluginBindingGenerator<TPluginInterface> : IBindingGenerator
{
private readonly Type pluginInterfaceType = typeof (TPluginInterface);
public void Process(Type type, Func<IContext, object> scopeCallback, IKernel kernel)
{
if(!pluginInterfaceType.IsAssignableFrom(type))
return;
if (type.IsAbstract || type.IsInterface)
return;
kernel.Bind(pluginInterfaceType).To(type);
}
}
You can then get all loaded plugins with kernel.GetAll<IPlugin>().
The advantages of this method are:
Your plugin dlls don't need to know that they are being loaded with ninject
The concrete plugin instances will be resolved by ninject, so they can have constructors to inject types the plugin host knows how to construct.
This question applies to the same answer I provided over here: Can NInject load modules/assemblies on demand?
I'm pretty sure this is what you're looking for:
var kernel = new StandardKernel();
kernel.Load( Assembly.Load("yourpath_to_assembly.dll");
If you look at KernelBase with reflector in Ninject.dll you will see that this call will recursively load all modules in the loaded assemblies (Load method takes an IEnumerable)
public void Load(IEnumerable<Assembly> assemblies)
{
foreach (Assembly assembly in assemblies)
{
this.Load(assembly.GetNinjectModules());
}
}
I'm using this for scenarios where I don't want a direct assembly reference to something that will change very frequently and I can swap out the assembly to provide a different model to the application (granted I have the proper tests in place)
Extending on #ungood good answer, which is based on v.2, with v.3 of Ninject (currently on RC3) it could be made even easier. You needn't any IPluginGenerator anymore, just write:
var kernel = new StandardKernel();
kernel.Bind(scanner => scanner.FromAssembliesInPath(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location))
.SelectAllClasses()
.InheritedFrom<IPlugin>()
.BindToAllInterfaces());
Please note I'm looking for plugins implementing IPlugin (put your interface here) in the same path of the application.
you can easily do it with normal C# reflection, you don't need any extra technology.
There are quite a few examples on the web, e.g.
http://www.codeproject.com/KB/cs/c__plugin_architecture.aspx
In general in your main application, you need to load the assembly implementing the plugin, e.g.:
ass = Assembly.Load(name);
and then you need to create an instance of your plugin. If you know the name of the class it would look like this:
ObjType = ass.GetType(typename);
IPlugin plugin = (IPlugin)Activator.CreateInstance(ObjType);
and then you just use it.
Take a look at Managed Extensibility Framework. http://www.codeplex.com/MEF
There are multiple ways to go about this and you already have accomplished the main goal to achieve this in having concrete implementations through pre-defined interfaces. Realistically, if your interfaces remain stable, you should be able to build off of your core application.
I am not sure how the implementation would work with Ninject, however. You can do this with the Provider Model or with reflection - although I think reflection is overkill, if you don't absolutely need to do it.
With the provider model approach, you place the file in the /bin folder, or any other folder that you are probing, and adjust the .config file to reflect the presence of the provider. If you have a specific "plugin" folder, you can create a method called at the startup of the application and periodically, otherwise, to scan for new or removed instances and reload the providers.
This would work in ASP.NET, under C# or VB. However, if you are doing some sort of other application, you would need to consider another approach. The provider is really just Microsoft's spin on the Strategy Pattern.
I got this as a hit for Activator.CreateInstance + Ninject and just wanted to point out something in this area - hopefully it will inspire someone to come up with a real killer answer to this question on SO.
If you havent yet gone to the trouble of auto-scanning Modules and classes and registering them with Ninject properly, and are still creating your plugin via Activator.CreateInstance, then you can post-CreateInstance inject the dependencies in via
IKernel k = ...
var o = Activator.CreateInstance(...);
k.Inject( o );
Of course, this would only be a temporary solution on the way to something like http://groups.google.com/group/ninject/browse_thread/thread/880ae2d14660b33c
I think no need to framework. This tutorial is solved your problem http://www.codeproject.com/KB/cs/c__plugin_architecture.aspx
The problem is that you might need to recompile if the object you setup in the load of your module are used inside the program. The reason is that you program might not have the latest version of the assembly of your class. Example, if you create a new concrete class for one of your interface, let say you change the plugin dll. Now, Injector will load it, fine but when it will be returned inside your program (kernel.get(...)) your program might not have the assembly and will throw an error.
Example of what I am talking about:
BaseAuto auto = kernel.Get<BaseAuto>();//Get from the NInjector kernel your object. You get your concrete objet and the object "auto" will be filled up (interface inside him) with the kernel.
//Somewhere else:
public class BaseModule : StandardModule
{
public override void Load(){
Bind<BaseAuto>().ToSelf();
Bind<IEngine>().To<FourCylinder>();//Bind the interface
}
}
If you have create a new FourCylinder called SixCylinder, your real program will not have any reference to your new object. So, once you will load from the PlugIn the BaseModule.cs you might get some trouble with the reference. To be able to do it, you will need to distribute the new dll of this concrete implementation with your plugin that will have the Module that Injector will require to load the Interface to Concrete class. This can be done without problem but you start to have a whole application that reside on loading from Plugin and it might be problematic in some points. Be aware.
BUT, if you do want some PlugIn information you can get some tutorial from CodeProject.

Categories

Resources