Skip to content

Implementing container support

hmemcpy edited this page Jun 6, 2012 · 5 revisions

In this module we will look at how to implement support for a DI container in Agent Mulder plugin. You should follow these instructions after you had created the project structure for a new container.

Getting started

The Agent Mulder plugin composes support for additional containers via MEF, by looking for assemblies that have an implementation of the interface IContainerInfo. This interface exposes 2 pieces of information: the name of the container (to be used in the hint message), and a list of patterns that will be matched against the code.

Assuming you added a class library for the new container in the previous step, and set the output directories to the correct location, the plugin will now take care of the composition without having to do anything else.

Create a new class in the root of the new project called _YourContainerName_ContainerInfo, e.g. AutofacContainerInfo, and implement IContainerInfo. You will need to add a reference to AgentMulder.ReSharper.Domain, which ReSharper can do automatically for you, then set Copy Local to False.

After implementing the interface, decorate the class with [Export(typeof(IContainerInfo))], to make this class visible to MEF. You will need to add a reference to System.ComponentModel.Composition. Again, ReSharper does this for you. Here is no need to set Copy Local.

Here's an example of a very simple implementation of AutofacContainerInfo:

[Export(typeof(IContainerInfo))]
public class AutofacContainerInfo : IContainerInfo
{
    private readonly List<IRegistrationPattern> registrationPatterns; 

    public string ContainerDisplayName
    {
        get { return "Autofac"; }
    }

    public IEnumerable<IRegistrationPattern> RegistrationPatterns
    {
        get { return registrationPatterns; }
    }
}

Creating patterns

The next step can be a bit tedious, as it requires breaking down the component registration syntax of the container into patterns, and then recreating those patterns in code. I find it best to use the "Search with Pattern" dialog of ReSharper to test my patterns before trying to write them in code.

Understanding the pattern

Consider the following Autofac Module syntax:

Using the "Search with Pattern" dialog in ReSharper, we could search for builder.RegisterType<CommonImpl>() by using the following pattern:

$builder$.RegisterType<$type$>(), where $builder$ is an Expression placeholder of type Autofac.ContainerBuilder (exact) and $type$ is a Type placeholder

In code, this pattern is translated to:

IStructuralSearchPattern pattern = new CSharpStructuralSearchPattern("$builder$.RegisterType<$type$>()",
    new ExpressionPlaceholder("builder", "global::Autofac.ContainerBuilder", true),
    new TypePlaceholder("type"))

Refer to ReSharper's Structural Search page for more detailed information.

Pattern matching

In Agent Mulder, the patterns are exposed through IContainerInfo, and then consumed by the plugin, attempting to find matches in the entire solution. The reason the patterns are broken into smaller patterns, is to make further matches only when the top match was found.

Something went wrong with that request. Please try again.