Search code examples
c#asp.net-mvcmodel-view-controllerdependency-injectionmef

How to get all composed and future composed MEF part's controllers in .net


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

    }

}

Solution

  • 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!