Monday 12 October 2015

Load multiple assemblies for MVC WEBAPI based N-tier MEF IOC Application

Microsoft Extended Framework can be used as a IOC and following is the simplest implementation we can have for a simple project.


 
[Import]
string message;

public class DisplayMessageBox
{
    [Export()]
    public string MyMessage
    {
        get { return "This is my example message."; }
    }
}

private void Compose()
{
    AssemblyCatalog catalog = new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly());
    CompositionContainer container = new CompositionContainer(catalog);
    container.SatisfyImportsOnce(this);
}

void Run()
{
    Compose();
    Console.WriteLine(message);
    Console.ReadKey();
}



The most important part is the compose method where it loads the assembly which is exporting the MyMessage property. This is working properly because there is only one assembly to load.
But how we can accomplish this when there are multiple projects in our solution and there are many assemblies to load to the catalog ? Following is a simple example of how we can load multiple assemblies from multiple projects. Im using a web api application to demonstrate this.
Solution's project layout

Our main project in this layout is the WebApi project. Hence, we need to initiate the MEF inside that project. But the problem is we have many reference assemblies. First of all, we need to configure post build properties of required projects as follows. This would copy the binaries to main project upon successful build.

copy "$(TargetFileName)" "$(SolutionDir)$(SolutionName)\bin"

We need to add following to the WebApi's startup class to initiate the MEF process.
 
 public void Configuration(IAppBuilder app)
        {
            ConfigureAuth(app);
            MefConfig.RegisterMef();
        }

Following is the MefConfig class.
In here we are loading required assemblies by name and iterating each and load them to the container.

 
 public static class MefConfig
    {
        public static CompositionContainer Container { get; private set; }
        public static void RegisterMef()
        {
            var files = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "VTracker*.dll", SearchOption.AllDirectories)
                .Where(o => !o.Replace(AppDomain.CurrentDomain.BaseDirectory, "").Contains(@"obj\"));

            var catalogAggregator = new AggregateCatalog();

            foreach (var file in files)
            {
                catalogAggregator.Catalogs.Add(new AssemblyCatalog(Assembly.LoadFrom(file)));
            }

            Container = new CompositionContainer(catalogAggregator);
            var resolver = new MefDependencyResolver(Container);
            // Install MEF dependency resolver for MVC
            DependencyResolver.SetResolver(resolver);
            // Install MEF dependency resolver for Web API
            System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = resolver;
        }

    }

No comments:

Post a Comment