How to use MEF to allow plugins to override existing functionality? - c#

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.

Related

C# how to "register" class "plug-ins" into a service class?

Update#2 as of year 2022
All these years have passed and still no good answer.
Decided to revive this question.
I'm trying to implement something like the idea I'm trying to show with the following diagram (end of the question).
Everything is coded from the abstract class Base till the DoSomething classes.
My "Service" needs to provide to the consumer "actions" of the type "DoSomethings" that the service has "registered", at this point I am seeing my self as repeating (copy/paste) the following logic on the service class:
public async Task<Obj1<XXXX>> DoSomething1(....params....)
{
var action = new DoSomething1(contructParams);
return await action.Go(....params....);
}
I would like to know if there is anyway in C# to "register" all the "DoSomething" I want in a different way? Something more dynamic and less "copy/paste" and at the same time provide me the "intellisense" in my consumer class? Somekind of "injecting" a list of accepted "DoSomething" for that service.
Update#1
After reading the sugestion that PanagiotisKanavos said about MEF and checking other options of IoC, I was not able to find exactly what I am looking for.
My objective is to have my Service1 class (and all similar ones) to behave like a DynamicObject but where the accepted methods are defined on its own constructor (where I specify exactly which DoSomethingX I am offering as a method call.
Example:
I have several actions (DoSomethingX) as "BuyCar", "SellCar", "ChangeOil", "StartEngine", etc....
Now, I want to create a service "CarService" that only should offer the actions "StartEngine" and "SellCar", while I might have other "Services" with other combination of "actions". I want to define this logic inside the constructor of each service. Then, in the consumer class, I just want to do something like:
var myCarService = new CarService(...paramsX...);
var res1 = myCarService.StartEngine(...paramsY...);
var res2 = myCarService.SellCar(...paramsZ...);
And I want to offer intellisense when I use the "CarService"....
In conclusion: The objective is how to "register" in each Service which methods are provided by him, by giving a list of "DoSomethingX", and automatically offer them as a "method"... I hope I was able to explain my objective/wish.
In other words: I just want to be able to say that my class Service1 is "offering" the actions DoSomething1, DoSomething2 and DoSomething3, but with the minimum lines as possible. Somehow the concept of the use of class attributes, where I could do something similar to this:
// THEORETICAL CODE
[RegisterAction(typeOf(DoSomething1))]
[RegisterAction(typeOf(DoSomething2))]
[RegisterAction(typeOf(DoSomething3))]
public class Service1{
// NO NEED OF EXTRA LINES....
}
For me, MEF/MAF are really something you might do last in a problem like this. First step is to work out your design. I would do the following:
Implement the decorator design pattern (or a similar structural pattern of your choice). I pick decorator as that looks like what you are going for by suplimenting certain classes with shared functionality that isn't defined in those clases (ie composition seems prefered in your example as opposed to inheritance). See here http://www.dofactory.com/net/decorator-design-pattern
Validate step 1 POC to work out if it would do what you want if it was added as a separate dll (ie by making a different CSProj baked in at build time).
Evaluate whether MEF or MAF is for right for you (depending on how heavy weight you want to go). Compare those against other techniques like microservices (which would philosophically change your current approach).
Implement your choice of hot swapping (MEF is probably the most logical based on the info you have provided).
You could use Reflection.
In class Service1 define a list of BaseAction types that you want to provide:
List<Type> providedActions = new List<Type>();
providedActions.Add(typeof(DoSomething1));
providedActions.Add(typeof(DoSomething2));
Then you can write a single DoSomething method which selects the correct BaseAction at run-time:
public async Task<Obj1<XXXX>> DoSomething(string actionName, ....params....)
{
Type t = providedActions.Find(x => x.Name == actionName);
if (t != null)
{
var action = (BaseAction)Activator.CreateInstance(t);
return await action.Go(....params....);
}
else
return null;
}
The drawback is that the Client doesn't know the actions provided by the service unless you don't implement an ad-hoc method like:
public List<string> ProvidedActions()
{
List<string> lst = new List<string>();
foreach(Type t in providedActions)
lst.Add(t.Name);
return lst;
}
Maybe RealProxy can help you? If you create ICarService interface which inherits IAction1 and IAction2, you can then create a proxy object which will:
Find all the interfaces ICarService inherits.
Finds realizations of these interfaces (using actions factory or reflection).
Creates action list for the service.
In Invoke method will delegate the call to one of the actions.
This way you will have intellisence as you want, and actions will be building blocks for the services. Some kind of multi-inheritance hack :)
At this point I am really tempted to do the following:
Make my own Class Attribute RegisterAction (just like I wrote on my "Theoretical" example)
Extend the Visual Studio Build Process
Then on my public class LazyProgrammerSolutionTask: Microsoft.Build.Utilities.Task try to find the service classes and identify the RegisterAction attributes.
Then per each one, I will inject using reflection my own method (the one that I am always copying paste)... and of course get the "signature" from the corresponding target "action" class.
In the end, compile everything again.
Then my "next project" that will consume this project (library) will have the intellisence that I am looking for....
One thing, that I am really not sure, it how the "debug" would work on this....
Since this is also still a theoretically (BUT POSSIBLE) solution, I do not have yet a source code to share.
Meanwhile, I will leave this question open for other possible approaches.
I must disclose, I've never attempted anything of sorts so this is a thought experiment. A couple of wild ideas I'd explore here.
extension methods
You could declare and implement all your actions as extension methods against base class. This I believe will cover your intellisense requirements. Then you have each implementation check if it's registered against calling type before proceeding (use attributes, interface hierarchy or other means you prefer). This will get a bit noisy in intellisense as every method will be displayed on base class. And this is where you can potentially opt to filter it down by custom intellisense plugin to filter the list.
custom intellisense plugin
You could write a plugin that would scan current code base (see Roslyn), analyze your current service method registrations (by means of attributes, interfaces or whatever you prefer) and build a list of autocomplete methods that apply in this particular case.
This way you don't have to install any special plugins into your Dev environment and still have everything functional. Custom VS plugin will be there purely for convenience.
If you have a set of actions in your project that you want to invoke, maybe you could look at it from CQS (Command Query Separation) perspective, where you can define a command and a handler from that command that actually performs the action. Then you can use a dispatcher to dispatch a command to a handler in a dynamic way. The code may look similar to:
public class StartEngine
{
public StartEngine(...params...)
{
}
}
public class StartEngineHandler : ICommandHandler<StartEngine>
{
public StartEngineHandler(...params...)
{
}
public async Task Handle(StartEngine command)
{
// Start engine logic
}
}
public class CommandDispatcher : ICommandDispatcher
{
private readonly Container container;
public CommandDispatcher(Container container) => this.container = container;
public async Task Dispatch<T>(T command) =>
await container.GetInstance<ICommandHandler<T>>().Handle(command);
}
// Client code
await dispatcher.Dispatch(new StartEngine(params, to, start, engine));
This two articles will give you more context on the approach: Meanwhile... on the command side of my architecture, Meanwhile... on the query side of my architecture.
There is also a MediatR library that solves similar task that you may want to check.
If the approaches from above does not fit the need and you want to "dynamically" inject actions into your services, Fody can be a good way to implement it. It instruments the assembly during the build after the IL is generated. So you could implement your own weaver to generate methods in the class decorated with your RegisterAction attribute.

C# make class auto-register

I have a number of types for which I need to provide custom functions that talk to the external world.
For example, I may have a Widget, and a Sprocket, and when data from the world that I don't control arrives and says "make a Widget," then I need to call a Widget.Create() function.
If the world says "make a Hammer," then I need to return a "Hammer does not exist" error.
However, the mapping between world-representation and type-name is not 1:1, so I can't simply use reflection to find the type name directly -- I need a table. (In fact, "name" may for example be a specific integer value.)
I understand how I can use a pre-defined table (or Dictionary) that maps from world-representation to class-name.
I also understand how to extend/change this table at runtime if the set of possible classes changes. (Because of rules changes, or dynamically loaded parts of the application, or whatever.)
However, all of that requires duplication -- I have to both implement my class, and then, in some other place in the code, remember to add an instance of "this class has this name in the external world."
This is a bit of a code smell, because sometime in the future I will write a new class (or delete an old class) and forget to update the table, and then spend time debugging why it doesn't work right.
I thought I could use a static member in each class which registers itself in a global table:
public static Registration Me = new Registration(typeid(MyClass), "My Name");
Unfortunately, static fields are not initialized until some function in the class is executed/accessed, so this doesn't run at start-up. (Static constructors have similar limitations, plus even more overhead in the runtime!)
The next idea was to decorate the class with a custom attribute that says "register this class in the table."
[Register("My Name")]
class MyClass : .... {
}
Unfortunately, the "Register" attribute doesn't know what class it is attached to -- only the MyClass class knows that it has the Register attribute. (This is infuriating to me, as it would be SO CONVENIENT if attributes knew where they were attached, in many, many cases. But that's an aside!)
So, the least bad implementation I can think of is to iterate all the types of all the assemblies, using reflection, and check whether they have this attribute, and if they do, register them in the table. This is, shall we say, neither elegant nor efficient.
Is there a better way to auto-register classes without having to update some other source file with a central registry?
You could also iterate over all classes matching some criteria and use RuntimeHelpers.RunClassConstructor to ensure the static initializers all get run.
Something like:
var baseType = typeof(MyType);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(a => a.GetTypes())
.Where(t => t.IsClass && !t.IsAbstract && t.IsSubclassOf(baseType));
foreach (var t in types)
{
RuntimeHelpers.RunClassConstructor(t.TypeHandle);
}
This should ensure all your
public static Registration Me = new Registration(typeid(MyClass), "My Name");
functions get called.
I have checked with other resources (that are quite knowledgeable about the internals of the CLR and IL) and it seems that this is a hole in the CLR and the C# language. There simply is no direct way of making things automatically happen on assembly load or appdomain preparation. Walking the types and finding the types that I'm interested in is the least bad way.
In fact, attributes aren't always created until some piece of code asks for them, so I can't use an attribute constructor with a type argument to auto-register, either!
This is of course not great, because if there are eight different pieces of code that each have their own kind of registration they want to do, each of those pieces have to iterate through all of the types and do the inspection on their own. The only way around that would be to give up on modularity, and make all of the different "things" that happen to types be centralized to a single walk-all-types loop at the start of the app. Third party libraries (including the MEF) still wouldn't go inside this loop, though, so there's just an unavoidable chunk of overhead here, OR an unavoidable piece of duplication -- my choice, as developer.

In Orchard CMS, is it possible to register IEventHandler implementations in modules to be called later than those that reside in Orchard.Framework?

I am writing a module for Orchard CMS that contains an event handler class that implements the IOrchardShellEvents interface.
When a stock implementation of Orchard is set up using the Core recipe, and I enable my module, there are just three active implementations of IOrchardShellEvents. By default they are called in this order:
My custom event handler (in my custom module)
AliasHolderUpdater (from the Orchard.Alias module)
AutomaticDataMigrations (from Orchard.Framework).
I would like to set these up so that when the applicable event is fired, my class is called later than AutomaticDataMigrations. I've tried playing with both the Dependencies and Priority fields in the Modules.txt of my module, but I cannot get my class to run later than AutomaticDataMigrations.
Things I have tried:
I have tried adding Dependencies: Orchard.Framework to my module's Module.txt. This seems to do nothing. However, when I add Dependencies: Orchard.Alias to Module.txt, my class is indeed called later than AliasHolderUpdater. It just does not work for AutomaticDataMigrations, which is part of Orchard.Framework.
I have tried adding Priority: 1 to my module's Module.txt. This does indeed cause my class to get called later than other IOrchardShellEvents implementations that exist in modules, such as AliasHolderUpdater. However, even then it still calls AutomaticDataMigrations last.
Looking at the ExtensionManager.AvailableFeatures method, it can be seen that all features are loaded in order of dependency and priority. This means that the actual IDependency objects from each module are registered with AutoFac in this order.
(Details can be seen in DependencyOrdering.OrderByDependenciesAndPriorities, CompositionStrategy.Compose, and ShellContainerFactory.CreateContainer methods)
I do not see a way to control the order of registration of classes that reside in modules relative to those that reside in Orchard.Framework, which is not an "Orchard Module" and does not follow the normal rules of module loading.
Because the purpose of AutomaticDataMigrations is to ensure that the latest database migrations have been run, I would like for my class to be called later than it, so that when my event handler runs I can be sure it can make use of the database tables set up by the migrations.
How can I register my class to run later than AutomaticDataMigrations? Or, will this require modification of Orchard itself?
I think I have found the answer to this problem and I believe it's actually a bug in Orchard.
Orchard.Environment.ShellBuilders.CompositionStrategy contains the following code:
var enabledFeatures = _extensionManager.EnabledFeatures(descriptor);
var features = _extensionManager.LoadFeatures(enabledFeatures);
if (descriptor.Features.Any(feature => feature.Name == "Orchard.Framework"))
features = features.Concat(BuiltinFeatures());
Feature descriptors are returned in "dependency" order from EnabledFeatures() -- items earlier in the list should not depend on items later in the list. This order is used when eventually building the dependency container.
Because Orchard.Framework should not depend on anything, and everything can depend on Orchard.Framework, this should come first ... and the code should look like this (only the last line here has been modified):
var enabledFeatures = _extensionManager.EnabledFeatures(descriptor);
var features = _extensionManager.LoadFeatures(enabledFeatures);
if (descriptor.Features.Any(feature => feature.Name == "Orchard.Framework"))
features = BuiltinFeatures().Concat(features);
This way, when dependencies are injected as part of a list (such as event handlers), built-in features should come first, since they have no dependencies.
This resolves my issue because I can rely on Orchard.Framework-provided IOrcharShellEvents implementations to be called before any provided by custom modules.
I have filed the above as a suggested fix in the Orchard issue tracker: http://orchard.codeplex.com/workitem/20286

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.

Multiple Decorator pattern in castle-windsor

We are in the process of redesigning some legacy software to be more testable and have decided upon Dependency-Injection and Castle.Windsor to help us.
First, our goal:
* A number of decorators that all work on a data stream.
* Multiple combinations of the decorators are possible and the root nodes in each case can be required to get data from different places.
Technically, our design is as follows:
interface IUpdateableValue<T>
{
T Get();
};
We have e.g. three sets of data to be retrieved with a number of components, all implementing IUpdateableValue() (Pseudo-code):
JsonParser(
Decompressor(
Decrypter(decryptionKey
FileCache(filename,
HttpWebDownloader(url))))
XmlParser(
Decompressor(
Decrypter(decryptionKey2
FileCache(filename2,
HttpWebDownloader(url2))))
I'm having trouble getting out design to fit into a DI-framework like Castle-Windsor. I suspect some of it could be handled by named instances, but this seems smelly for this usage.
The idea is that the "user" of e.g. the JsonParser and XmlParser instances don't know (or care) whether data comes from a HttpUrl, a file or magically pulled out of a hat.
I'm thinking there is something wrong in our design, but unsure how to fix it.
Any ideas on how to progress?
With Castle Windsor you can implicitly configure decoraters by registering them in the correct order. You need to register the outer decorater first:
container.Register(Component
.For<IUpdateableValue>()
.ImplementedBy<JsonParser>());
container.Register(Component
.For<IUpdateableValue>()
.ImplementedBy<Decompressor>());
container.Register(Component
.For<IUpdateableValue>()
.ImplementedBy<Decrypter>());
...
When you resolve IUpdateableValue Caste Windsor will automatically wire up the dependencies, so they are nested correctly.

Categories

Resources