I am trying to create a generic payment processor that can be added on as modules on runtime by using MEF composition. I currently have code that will compose all the available .dlls and have testing it successfully by accessing its controls.
I currently want to be able to get all the controllers that are available from the compositionContainer. I have looked everywhere but only find ones that invoke controllers that do not reside somewhere else, but within the main project.
My question is, how can I access ALL the controllers currently composed and not just find it by its contract name. Since I want to enumerate through them and call certain methods accordingly
This is how I compose the dlls, I have a custom bootstrapper tha handles the composition and then a MefControllerFactory that handles the fetching of the controller based on the contract name.
using System;
using System.Web.Mvc;
using System.ComponentModel.Composition.Hosting;
using System.Linq;
using System.Web.Routing;
using System.Web.SessionState;
using System.Composition;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
namespace Dependency_Injection_MEF_MVC.Components
{
public class MefControllerFactory : IControllerFactory
{
//private string pluginPath;
//private DirectoryCatalog catalog;
//private CompositionContainer container;
private DefaultControllerFactory _defaultControllerFactory;
public MefControllerFactory(){
_defaultControllerFactory = new DefaultControllerFactory();
//this.pluginPath = pluginPath;
//this.catalog = new DirectoryCatalog(pluginPath);
//this.container = new CompositionContainer(catalog);
//this.defaultControllerFactory = new DefaultControllerFactory();
}
public IController CreateController(RequestContext requestContext, string controllerName)
{
if (controllerName.Contains("Home") || controllerName.Contains("Bundels"))
return _defaultControllerFactory.CreateController(requestContext,controllerName);
var controller = Bootstrapper.GetInstance<IController>(controllerName);
if (controller == null)
throw new Exception("Controller not found!");
return controller;
}
public SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName)
{
return SessionStateBehavior.Default;
}
public void ReleaseController(IController controller)
{
var disposableController = controller as IDisposable;
if (disposableController != null)
{
disposableController.Dispose();
}
}
}
}
After much research I have figured out how to achieve this by using the compositionContainer
Bootstrapper.getInstance
is just calling CompositionContainer.getExportedValue<T>()
ViewBag.count = Bootstrapper.getCompositionContainer().Catalog.Count();`
List<String> controllerstoImport = new List<string>();
foreach(var cat in Bootstrapper.getCompositionContainer().Catalog){
foreach(var cats in cat.ExportDefinitions){
controllerstoImport.Add(cats.ContractName);
}
}
List<IController> MEFcontrollers = new List<IController>();
foreach(var contractName in controllerstoImport){
MEFcontrollers.Add(Bootstrapper.GetInstance<IController>(contractName));
}
List<Type> compoundControllerType = new List<Type>();
foreach(var controllerType in MEFcontrollers){
compoundControllerType.Add(controllerType.GetType());
}
And then this is how I would extract all the methods from the MEF module controller List methodList = new List();
foreach (var controllersInfo in compoundControllerType){
listo.Add(controllersInfo.GetMethods());
}
List<String> methods = new List<string>();
foreach(var method in methodList){
foreach (MethodInfo info in method){
methods.Add(info.Name);
}
}
Finally works, took way more research than needed. I am sure there is a better much faster solution, so if anyone has any code improvements please leave another answer. Thanks!