StructureMap: Dynamically load Registry’s in a specific order

by scott on 03/16/2011

Structuremap makes it easy to dynamically load and configure Registry objects at runtime.

Here is an example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Bootstrapper
{
    public static void Bootstrap()
    {
        ObjectFactory.Initialize(init =>
        {
            init.Scan(scan =>
            {
                scan.AssembliesFromPath(path);
                scan.LookForRegistries();
            });
        });
    }
}

However, I ran into a problem where I have multiple registries in multiple Assemblies that need to be registered in a specific order.

To solve this problem I created a RegistryOrderAttribute that I can tack onto my registry classes like [RegistryOrder(Order = 1)]

This is what the RegistryOrderAttribute looks like:

1
2
3
4
5
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class RegistryOrderAttribute : Attribute
{
    public int Order { get; set; }
}

Then I changed my ObjectFactory Initialization code to find and filter Registry types by the order and add them to the ObjectFactory:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
public class Ioc
{
    public static void Bootstrap(string path)
    {

        var registries = FindAssemblies(path)
            .Where(a => a != null)
            .SelectMany(x => x.GetTypes())
            .Where(t => t.IsSubclassOf(typeof (Registry)))
            .Select(
                t => new
                         {
                             Type = t,
                             Attribute = t.GetCustomAttributes(false)
                         .OfType<RegistryOrderAttribute>().FirstOrDefault()
                         });

        var sortedRegistries = registries.Where(a => a.Attribute != null).OrderBy(a => a.Attribute.Order);

        ObjectFactory.Initialize(init =>
                                     {
                                         foreach (var registry in sortedRegistries)
                                         {
                                             init.AddRegistry(Activator.CreateInstance(registry.Type) as Registry);
                                         }
                                     });

        ObjectFactory.AssertConfigurationIsValid();
    }

    private static IEnumerable<Assembly> FindAssemblies(string path)
    {
        return Directory.GetFiles(path)
            .Where(file => Path.GetExtension(file).Equals(".exe", StringComparison.OrdinalIgnoreCase) ||
                           Path.GetExtension(file).Equals(".dll", StringComparison.OrdinalIgnoreCase))
            .Select(p =>
                        {
                            try
                            {
                                return Assembly.LoadFrom(p);
                            }
                            catch (Exception)
                            {
                                return null;
                            }
                        });
    }

    public static T GetInstance<T>()
    {
        return ObjectFactory.GetInstance<T>();
    }

    public static IEnumerable<T> GetAllInstances<T>()
    {
        return ObjectFactory.GetAllInstances<T>();
    }
}

Comments are closed.