Plugin Framework for Win-Rt - c#

I was looking at Microsoft.Composition but i don't think that is quite what i want. I have a bunch of UserControls, that are each build into it's own assembly, but they each extend the same interface. What would be the best way to scan a directory, see what UserControl assembly is present and allow the program to use the controls that are present.
I would love to stay away from reflection.

The IDriver is a Interface that all drivers must extend, so we get the driver name, add the driver namespace and use the Activator to create the instance
Type driverType = Type.GetType(string.Format("Win8App.RDriver.Drivers.{0}", driver));
if (driverType != null)
{
return (IDriver)Activator.CreateInstance(driverType);
}
log.Error(string.Format("Could not load driver Win8App.RDriver.Drivers.{0}", driver));
return null;

Related

Single .dll with MEF

With reflection i can load a single dll.
Assembly testAssembly = Assembly.LoadFile(#"c:\Test.dll");
But with MEF all the plugins in the directory are red.
Is there a way with MEF of doing the same ?
I can do this :
public IPlugn Load(string name)
{
return Plugins
.Where(l => l.Name.Equals(name))
.FirstOrDefault();
}
but this is a based on the the whole list of plugins.
Kind regards
Dipke
Catalogs are the mechanism MEF uses to find plugins - and they are very flexible.
You are presumably using a DirectoryCatalog?
If so, you can use the overload of the constructor that takes a search pattern:
var catalog = new DirectoryCatalog("C:\\", "Test.dll");
Alternatively, you can use the AssemblyCatalog, which will allow you to just specify the assembly to use.
var catalog = new AssemblyCatalog(Assembly.LoadFile("C:\\Test.dll"));
Finally, if you want any really specific behaviour (load plugins from a web-service call, or crazy stuff like that), then you can just implement your own ComposablePartCatalog.

MEF DirectoryCatalog reads the same dll many times

I had a simple implementation of MEF loading some dlls (plugins) from a directory. This was running well under MEF1 but now I want to use the same functionality with MEF2 and it gives me an IEnumerable that contains the right count of dlls that are in the directory but all the assemblies the same.
For example I have two assemblies: fakeplugin1.dll and fakeplugin2.dll in the directory. They exports FakePlugin1 and FakePlugin2 classes. Now when I call container.ComposeParts() I don't have anything in the list decorated with ImportMany and container.Catalog contains two assemblies in the directory but both of them are FakePlugin1.
Here's the code:
[ImportMany(typeof (IDCPlugin))]
IEnumerable<IDCPlugin> workplaceControllers;
var catalog = new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory);
var agcatalogue = new AggregateCatalog(catalog);
var container = new CompositionContainer(agcatalogue);
container.ComposeParts();
I am trying to use ExportFactory and RegistrationBuilder but I've just realized that even the base functionality donesn't work as expected.
What am I doing wrong? Has something changed in MEF2 I should know? How to load the two different assemblies? :)
Thanks for your help in advance!
Edit:
It always creates two instances of the first type in the folder (ascending in abc). If I put an other one in the folder it creates three of the same, etc.
Edit:
I have uploaded code to pastebin that gives the same result with MEF2: http://pastebin.com/3fWcujPS
A catalog will contain Import and Export definitions for anything detected. Regardless of if you actually need it.
This is a 'feature' of MEF. You will need to either ImportMany and selectively filter the plugins you require.
So how do you handle multiple plugins gracefully? Try this:
[Export]
public class PluginService
{
public const string BEST_PLUGIN = "BestPlugin";
[ImportMany]
public IEnumerable<Plugin> Plugins{ private get; set; }
[Export(BEST_PLUGIN)]
public Plugin BestPlugin{ get { return GetBestPlugin(); } }
Plugin GetBestPlugin()
{
return Plugins.FirstOrDefault(); //or some other logic for selection
}
}
If your plugins are resource intensive, you may want to consider Lazy initialization.
Lazy<T, TMetadata> is a type provided by MEF to hold indirect
references to exports. Here, in addition to the exported object
itself, you also get export metadata, or information that describes
the exported object. Each Lazy<T, TMetadata> contains an IOperation
object, representing an actual operation, and an IOperationData
object, representing its metadata.
http://msdn.microsoft.com/en-us/library/dd460648.aspx#further_imports_and_importmany
MEF has strong rules on component cardinality (number of things) to ensure that there are never any surprises but this does mean you have to be careful with your deployment.

How to use MEF to allow plugins to override existing functionality?

I'm using MEF to allow users to extend my C# library. It's working great so far, but right now I'm trying to use it in a way I haven't seen it used before.
The primary use case for MEF I've seen so far is this:
Application exposes primitive interface (IPerson)
External library uses MEF and primitive interfaces to extend functionality of main library (e.g. IPoliceman : IPerson, adds functionality)
Application then uses ImportMany to search for correct IPerson depending on what it must do
But I need something like this: Let's say I have a tax calculator that takes a bunch of parameters and returns estimated tax depending on those parameters. I want users to be able to create plugins with MEF that modify how those calculations are done. Only one plugin that does this should be able to be loaded at any one time. Otherwise, how do I decide which alternate implementation to use?
So basically, my question boils down to this: Usually MEF allows adding implementations of classes and methods. How do I use it to allow users to replace an implementation?
Normally when you try to override an export which is already present in the application, you will get a cardinality exception for an [Import(typeof(IFoo)] because MEF expects exactly one matching export to be available.
However, you can put your plugins in a separate export provider and give it priority. Here I do that for a "plugins" subfolder inside the application folder:
Assembly executingAssembly = Assembly.GetExecutingAssembly();
string exeLocation = Path.GetDirectoryName(executingAssembly.Location);
string pluginPath = Path.Combine(exeLocation, "plugins");
var pluginCatalog = new DirectoryCatalog(pluginPath);
var pluginExportProvider = new CatalogExportProvider(pluginCatalog);
var appCatalog = new DirectoryCatalog(exeLocation,"*");
var appExportProvider = new CatalogExportProvider(appCatalog);
var container = new CompositionContainer(
pluginExportProvider, appExportProvider);
pluginExportProvider.SourceProvider = container;
appExportProvider.SourceProvider = container;
The order of the export providers as passed to the composition container determines the priority: if an export is provided by both the plugins and the application parts, then the plugins will get priority.
What you're talking about is actually just a different way of looking at the same problem. The answer is simpler than it sounds - for any behavior that you want a client to be able to override, just put that behavior in a plugin.
There's nothing that says you can't write plugins just because you're the author of the application. Put your TaxCalculator class in a plugin, and expose an interface allowing users to write their own tax calculators. At runtime, if you have more than one loaded, favor the one that isn't yours. Out-of-the-box, you will be using your tax calculator plugin, so it will work exactly the way you expect. If the user creates their own tax calculator plugin and drops it in the right directory, you use it instead, effectively allowing them to "override" your original functionality.
I'm not sure how much sense is going to make, but let me try.
I would make a TaxCalculatorManager class. That class could load all of the ITaxCalculator implementations from MEF. From there, you could have something in the Export attribute that would allow ranking of the implementations. Then when you need to calculate the taxes, you would call TaxCalculatorManager.Calculate which would rank the ITaxCalculator implementations and call Calculate on the winner.
Let me know if you need me to clarify any points.

Generate .net dll wrapper around existing .net library

I have a dll named ExpensiveAndLargeObfuscatedFoo.dll.
Lets says it defines a type named ExpensiveAndLargeObfuscatedFooSubClass.
It's been compiled for .NET.
Are there any tools (free, paid, whatever) that will generate c# or vb class files that will do nothing but wrap around everything defined in this expensive dll? That way I can add functionality, fix bugs (that CorpFUBAR won't fix), add logging, etc?
Literally, I want output that looks like this
namespace easytoread {
public class SubClass {
private ExpensiveAndLargeObfuscatedFoo.SubClass _originalSubClass;
public SubClass() {
this._originalSubClass = new ExpensiveAndLargeObfuscatedFoo.SubClass ();
}
public string StupidBuggyMethod(string param1,int param2) {
return _originalSubClass.StupidBuggyMethod(param1, param2);
}
}
}
It would have to handle custom return types as well as primitives
namespace easytoread {
public class SubFooClass {
private ExpensiveAndLargeObfuscatedFoo.SubFooClass _originalSubFooClass;
public SubFooClass() {
this._originalSubFooClass= new ExpensiveAndLargeObfuscatedFoo.SubFooClass ();
}
private SubFooClass(ExpensiveAndLargeObfuscatedFoo.SubFooClass orig) {
this._originalSubFooClass = orig;
}
public SubFooClass StupidBuggyMethod(string param1,int param2) {
return new SubFooClass(_originalSubFooClass.StupidBuggyMethod(param1, param2));
}
}
}
And so on and so forth for every single defined class.
Basically, poor mans dynamic proxy? (yay, Castle Project is awesome!)
We'd also like to rename some of our wrapper classes, but the tool doesn't need to do that.
Without renaming, we'd be able to replace the old assembly with our new generated one, change using statements and continue on like nothing happened (except the bugs were fixed!)
It just needs to examine the dll and do code generation. the generated code can even be VB.NET, or ironpython, or anything CLR.
This is a slippery slope and I'm not happy that I ended up here, but this seems to be the way to go. I looked at the Castle Project, but unless I'm mistaken that won't work for two reasons: 1) I can't rename anything (don't ask), 2) none of the assemblies methods are declared virtual or even overridable. Even if they were, there's hundreds of types I'd have to override manually, which doesn't sound fun.
ReSharper can do much of the work for you.
You will need to declare a basic class:
namespace easytoread {
public class SubClass {
private ExpensiveAndLargeObfuscatedFoo.SubClass _originalSubClass;
}
}
Then, choose ReSharper > Edit > Generate Code (Alt+Ins), select "Delegating Members", select all, and let it generate the code.
It won't wrap return values with custom classes (it will return the original type), so that would still have to be added manually.
It seems the best answer is "There is no such tool". So, I'll be taking a stab at writing my own later as an off-hours project. If I ever get something useful working I'll github it and update here.
UPDATE
Visual Studio 2012 Fakes seem to be promising. http://msdn.microsoft.com/en-us/library/tfs/hh549175(v=vs.110).aspx - we've moved on but I might try creating a fake and then dropping it in as a replacement dll sometime in the future
If you have access to the source code, rename and fix in the source
code.
If you don't have access (and you can do it legally) use some
tool like Reflector or dotPeek to get the source code and then,
goto to the first point.

C# create DLL Plugin that implements interface

I'm writing a simple plugin based program. I have an interface IPlugin which has some methods and functions, and a List<Plugin> in my main program. For the sake of simplicity, lets say its defined like this:
public interface IPlugin
{
public void OnKeyPressed(char key);
}
Everytime a key is pressed, I loop through the Plugin list, and call OnKeyPressed(c) on each of them.
I can create a class like so, and add it to the list...
public class PrintPlugin
{
public void OnKeyPressed(char key)
{
Console.WriteLine(c);
}
}
And then whenever you press a key, its printed out. But I want to be able to load plugins from DLL files. This link was helpful, but it doesn't explain how to have the classes in the DLL implement my IPlugin interface... How can I do that? I really don't want to have to copy the IPlugin.cs file every time I want to make a plugin...
If I am understanding you correctly...
Create 3 Projects:
Project 1: Your main program (the one with List in it)
Project 2: the project with your interface
public interface IPlugin
{
public void OnKeyPressed(char key);
}
Project 3: A sample Plugin
public class PrintPlugin : IPlugin
{
public void OnKeyPressed(char key)
{
Console.WriteLine(c);
}
}
Then Add project 2 as a reference to both project 1 and 3.
This way you share the interface with both your main project and any of your plugins.
I have used this on a couple of projects and it has served me well.
You may want to look into the Managed Extensibility Framework as well. It provide a complete API for writing plugin based programs and covers a lot of concerns such as security if you're ever going to plan to make the plugin API available to third parties.
If you need to load user defined plugins, you should search for new DLLs when the application starts (or any other action). This can be done by using:
1) AppDomain.CurrentDomain.GetAssemblies() method returns the list of loaded assemblies in the current AppDomain
2) Search all DLLs in a folder where plugins should be positioned and check if a certain assembly is in the list. If not, use the Assembly.Load method to load this assembly, find the IPlugin class in it and finally add it to the List object.

Categories

Resources