MEF = may experience frustration? - c#

UPDATE
As I've tried to get MEF working throughout my application, I'm coming across more an more places where I just don't get why it's not automatically creating my library when I expect it to. I think it all comes back to what Reed was saying about needing MEF to create everything. So right now, I have an XML reader class that needs to use my CandySettings, but even though its ICandySettings property has the [Import] attribute, it doesn't get imported. First I found out that [Import] doesn't work on statics, so I changed this. But after that it still didn't work. I think it's because I manually create the XML reader object, and what MEF wants me to do instead is to [Import] the XML reader... which means that I now have to have an interface for that as well.
It's almost like using IoC (or for MEF, at least), it's an all-or-nothing affair. You can't just arbitrarily use it here and there, because ultimately whatever class you want to inject properties into also needs to be created by MEF.
Please correct me if I am wrong!
Original post
Well, it's not THAT bad yet. :) But I do have questions after Reed has pointed me at MEF as a potential alternative to IoC (and so far it does look pretty good).
Consider the following model:
alt text http://bit.ly/9W0sHt
As you can see, I have an App, and this app uses Plugins (whoops, missed that association!). Both the App and Plugins require usage of an object of type CandySettings, which is found in yet another assembly.
I first tried to use the ComposeParts method in MEF, but the only way I could get this to work was to do something like this in the plugin code.
var container = new CompositionContainer();
container.ComposeParts(this, new CandySettings());
But this doesn't make any sense, because why would I want to create the instance of CandySettings in the plugin? It should be in the App. But if I put it in the App code, then the Plugin doesn't magically figure out how to get at ICandySettings, even though I am using [Import] in the plugin, and [Export] in CandySettings. EDIT (probably because I should be calling ComposeParts() from the App and then passing it the plugin?)
The way I did it was to use MEF's DirectoryCatalog, because this allows the plugin, when constructed, to scan all of the assemblies in the current folder and automagically import everything that is marked with the [Import] attribute. So it looks like this, and potentially in every plugin:
var catalog = new DirectoryCatalog(".");
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
This totally works great, but I can't help but think that this is not how MEF was intended to be used?

The "trick" here is that you want to have MEF create your plugins for you.
The way you'll do this is to have your Application compose itself, with the Plugin types specified:
class PluginRepository
{
[ImportMany(typeof(IPlugin))]
IEnumerable<IPlugin> Plugins { get; set; }
}
If you do this, and have MEF Compose your "repository" class, MEF will construct the objects. It'll then automatically Compose those as it constructs them, so ICandySettings will get composed without any intervention for you.
You only need to manually "compose" an object if MEF isn't constructing it for you.

Related

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 Use Ninject

I have been trying to use Ninject today and have a couple of questions. First of all do I need to use the Inject attribute on all constructors that I want to use injection for. This seems like a really lame design? Do I need to create a Kernel then use that everywhere I pass in an injected class?
The best way to get started with Ninject is to start small. Look for a new.
Somewhere in the middle of your application, you're creating a class inside another class. That means you're creating a dependency. Dependency Injection is about passing in those dependencies, usually through the constructor, instead of embedding them.
Say you have a class like this, used to automatically create a specific type of note in Word. (This is similar to a project I've done at work recently.)
class NoteCreator
{
public NoteHost Create()
{
var docCreator = new WordDocumentCreator();
docCreator.CreateNewDocument();
[etc.]
WordDocumentCreator is a class that handles the specifics of creating a new document in Microsoft Word (create an instance of Word, etc.). My class, NoteCreator, depends on WordDocumentCreator to perform its work.
The trouble is, if someday we decide to move to a superior word processor, I have to go find all the places where WordDocumentCreator is instantiated and change them to instantiate WordPerfectDocumentCreator instead.
Now imagine that I change my class to look like this:
class NoteCreator
{
WordDocumentCreator docCreator;
public NoteCreator(WordDocumentCreator docCreator) // constructor injection
{
this.docCreator = docCreator;
}
public NoteHost Create()
{
docCreator.CreateNewDocument();
[etc.]
My code hasn't changed that much; all I've done within the Create method is remove the line with the new. But now I'm injecting my dependency. Let's make one more small change:
class NoteCreator
{
IDocumentCreator docCreator;
public NoteCreator(IDocumentCreator docCreator) // change to interface
{
this.docCreator = docCreator;
}
public NoteHost Create()
{
docCreator.CreateNewDocument();
[etc.]
Instead of passing in a concrete WordDocumentCreator, I've extracted an IDocumentCreator interface with a CreateNewDocument method. Now I can pass in any class that implements that interface, and all NoteCreator has to do is call the method it knows about.
Now the tricky part. I should now have a compile error in my app, because somewhere I was creating NoteCreator with a parameterless constructor that no longer exists. Now I need to pull out that dependency as well. In other words, I go through the same process as above, but now I'm applying it to the class that creates a new NoteCreator. When you start extracting dependencies, you'll find that they tend to "bubble up" to the root of your application, which is the only place where you should have a reference to your DI container (e.g. Ninject).
The other thing I need to do is configure Ninject. The essential piece is a class that looks like this:
class MyAppModule : NinjectModule
{
public override void Load()
{
Bind<IDocumentCreator>()
.To<WordDocumentCreator>();
This tells Ninject that when I attempt to create a class that, somewhere down the line, requires an IDocumentCreator, it should create a WordDocumentCreator and use that. The process Ninject goes through looks something like this:
Create the application's MainWindow. Its constructor requires a NoteCreator.
OK, so create a NoteCreator. But its constructor requires an IDocumentCreator.
My configuration says that for an IDocumentCreator, I should use WordDocumentCreator. So create a WordDocumentCreator.
Now I can pass the WordDocumentCreator to the NoteCreator.
And now I can pass that NoteCreator to the MainWindow.
The beauty of this system is threefold.
First, if you fail to configure something, you'll know right away, because your objects are created as soon as your application is run. Ninject will give you a helpful error message saying that your IDocumentCreator (for instance) can't be resolved.
Second, if management later mandates the user of a superior word processor, all you have to do is
Write a WordPerfectDocumentCreator that implements IDocumentCreator.
Change MyAppModule above, binding IDocumentCreator to WordPerfectDocumentCreator instead.
Third, if I want to test my NoteCreator, I don't have to pass in a real WordDocumentCreator (or whatever I'm using). I can pass in a fake one. That way I can write a test that assumes my IDocumentCreator works correctly, and only tests the moving parts in NoteCreator itself. My fake IDocumentCreator will do nothing but return the correct response, and my test will make sure that NoteCreator does the right thing.
For more information about how to structure your applications this way, have a look at Mark Seemann's recent book, Dependency Injection in .NET. Unfortunately, it doesn't cover Ninject, but it does cover a number of other DI frameworks, and it talks about how to structure your application in the way I've described above.
Also have a look at Working Effectively With Legacy Code, by Michael Feathers. He talks about the testing side of the above: how to break out interfaces and pass in fakes for the purpose of isolating behavior and getting it under test.
First of all do I need to use the Inject attribute on all constructors
that I want to use injection for. This seems like a really lame
design?
No you shouldn't have to do this at all actually. Since you work with ASP.NET MVC you can just install the Ninject.MVC3 Nuget package. This will get you started with a NinjectMVC3 class in the App_Start folder. You can use the RegisterServices method to register your interfaces/classes with Ninject. All controllers that have dependencies to those interfaces will then be automatically resolved by Ninject, there is no need for the Inject attribute.
Do I need to create a Kernel then use that everywhere I pass in an
injected class?
No - what you are describing sounds more like the Service Locator pattern, not dependency injection - you will want to pass in your dependencies ideally in the constructor, instead of resolving them within particular classes using the kernel. There should be just one central composition root where the resolving is done, which is within the composition root in either the RegisterServices method mentioned above or a separate Ninject module instantiated there - the later approach will allow you a little more flexibility and modularity (no pun intended) in changing how you resolve your dependencies.
Here's a good beginner's tutorial on dependency injection with Ninject and MVC3.
Don't forget there are docs, including an intro I feel would be very appropriate given the sort of questions you are asking on the Ninject Wiki. You're just annoying yourself if you're trying to use Ninject without reading it end to end.
Stick the table of contents on your bookmark bar for a bit.
I can also highly recommend Mark Seemann's Dependency Injection in .Net as a companion book for DI based architecture (even though it doesnt directly cover Ninject).

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();

Multiple plugin instance loading with MEF

In my last application, using MEF to load plugins went just fine, but now I'm running into a new issue. I have a solution for it that I explain at the end of this question, but I'm looking for other ways to do it.
Let's say I have an interface called ApplianceInterface. I also have two plugins that inherit from ApplianceInterface, let's call them Blender and Processor. Now, I would like to have multiple Blenders and Processors in my application, but I am not sure how to instantiate them properly.
Before, I would simply use the ImportMany attribute and upon calling ComposeParts, my application would load Blender and Processor. For example:
[ImportMany(typeof(ApplianceInterface))]
private IEnumerable<ApplianceInterface> Appliances { get; set; }
and my Blender and Processor plugins would be attributed like this:
[PartCreationPolicy(CreationPolicy.NonShared)]
[Export(typeof(MyInterface)]
public class Blender : ApplianceInterface
{
...
}
but what this ends up doing for me is populating Appliances with one Blender and one Processor. I need to be able to create an arbitrary number of Blender and Processor objects.
Now, from the documentation I understand that [PartCreationPolicy(CreationPolicy.NonShared)] is what allows MEF to create a new instance each time, but is there a similar "magical" way to create a specific number of instances of something using MEF? Up until now, I've relied on [Import] and [ImportMany] to resolve the assemblies.
Is my only option to use a global container, and then resolve the export manually using GetExportedValue<>? I have tried GetExportedValue<> and that implementation does work fine for me, but I was just curious if there is a better, more accepted way to do it.
UPDATE
I just realized a big mistake, and GetExportedValue<> isn't what I really want. I'm iterating over an IEnumerable, and when I get a match (based on some parameters), I want to instantiate a new object of the current value. GetExportedValue<> ends up failing in the case where I have two different plugins that both export ApplianceInterface.
I think my question is different now, and is probably a C# specific one.
ExportFactory is what you are looking for, but it is currently only available in Silverlight. Here is a question that explains how to handle this on the desktop: Multiple Instances of a single MEF DLL

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