tags:

views:

162

answers:

2

Hi,

I am exploring the possibility of using StructureMap to load all instances of my plugin type IPlugin from a specific directory using the Scan feature.

When a plugin is registered with StructureMap I would like to call an Init method that would register the plugin in the database if it was the first time it had been seen.

Is there a way to "foreach" through the registered IPlugins, obtain a reference and call Init on each one?

I am aiming for drag and drop plugin installation.

Thanks,

Ian

+2  A: 

You can easily look at all the plugins which are configured for the container using the Model property off the container. Here is an example with the strong cavet. This is likely not what you are looking for. It is just an example of a couple of the ways I dreamt up to initialize things that you register in the container.

public interface IInitable
{
    void Init();
    bool Inited { get; }
}

public abstract class Initable : IInitable
{
    public bool Inited { get; private set; }

    public void Init()
    {
        Inited = true;
    }
}

public class Initable1 : Initable { }
public class Initable2 : Initable { }

[TestFixture]
public class accessing_the_container_model
{
    [Test]
    public void put_things_in_and_init_then_during_construction()
    {
        var container = new Container(cfg =>
        {
            cfg.For<IInitable>().Use(c =>
            {
                var initable = c.GetInstance<Initable1>();
                initable.Init();
                return initable;
            });
        });

        container.GetAllInstances<IInitable>().Each(i => i.Inited.ShouldBeTrue());
    }

    [Test]
    public void put_things_in_and_init_them()
    {
        var container = new Container(cfg =>
        {
            cfg.For<IInitable>().HybridHttpOrThreadLocalScoped().Add<Initable1>();
            cfg.For<IInitable>().HybridHttpOrThreadLocalScoped().Add<Initable2>();
        });

        foreach (var instance in container.Model.GetAllPossible<IInitable>())
        {
            instance.Init();
        }

        container.GetAllInstances<IInitable>().Each(i=>i.Inited.ShouldBeTrue());
    }
}
KevM
That's a great starting point. Thanks for the detailed answer.
madcapnmckay
+1  A: 

Using the assembly scanner is a great way to create a plug-in model.

public class StructuremapBootstrap
{
    public IContainer Container { get; private set; }

    public StructuremapBootstrap()
    {
        Container = new Container(x =>
        {
            //add registries here or do your config.

            //extensibility
            x.Scan(scan =>
            {
                                //some plugin discriminator
                scan.AssembliesFromApplicationBaseDirectory(a => a.FullName.Contains("Plugin")); 

                scan.LookForRegistries();
                scan.AddAllTypesOf<IInitable>();
            });
        });
    }
}

You basically tell StructureMap to look for all the assemblies having a certain discriminator, I've also used a marker assembly attribute. The LookForRegistries scanner is handy to allow your plug-in assemblies to configure StructureMap as they please. Lastly you have the scanner add your desired plug-in type.

KevM