« Home

Type Pool

The Type Pool concept comes from working with the Fubu code base its a pretty simple class that I find makes type scanning much simpler.

namespace v23athletics.infrastructure.types
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;
    using Fasterflect;

    public class TypePool
    {
        readonly IList<Assembly> _assemblies;
        Lazy<IEnumerable<Type>> _types;

        public TypePool(params Assembly[] assemblies)
        {
            _assemblies = new List<Assembly>(assemblies);
            _types = new Lazy<IEnumerable<Type>>(buildUp);
        }
        public TypePool() : this(new Assembly[0])
        {
        }

        public Assembly[] Assemblies { get { return _assemblies.ToArray(); } }

        //add a source to scan.
        public void AddSource(Assembly assembly)
        {
            _assemblies.Add(assembly);
            _types = new Lazy<IEnumerable<Type>>(buildUp);
        }

        //for LINQ queries
        public IEnumerable<Type> Query()
        {
            return _types.Value;
        }

        //if you want to have the scans be seperate testable classes
        public IEnumerable<Type> Scan<TScanner>() where TScanner : TypeScan, new()
        {
            var scanner = new TScanner();
            return _types.Value.Where(scanner.Matches);
        }

        public IEnumerable<Type> Scan(Func<Type, bool> predicate)
        {
            return _types.Value.Where(predicate);
        }

        //function to build the types up lazily
        IEnumerable<Type> buildUp()
        {
            return _assemblies.SelectMany(a => a.ExportedTypes);
        }

        public IEnumerable<Type> FindImplementorsOf<TInterface>()
        {
            return Scan(t => t.Implements<TInterface>());
        }
    }
}
var typePool = new TypePool(typeof(MarkerType).Assembly);
var settingTypes = typePool.Query().Where(t=>t.Name.EndsWith("Settings"));

I use this guy to help me find types so that i can register them in my IoC container. Now most containers have their own scanning conventions, but one thing they tend to lack is a way to pass around the ‘Application Assemblies’ which is is something the TypePool can do. By passing the TypePool into the lower services or IoC ‘Registries’ I can use there scanning capabilities or I can use my own.

public class MySubRegistry : Registry
{
    public MySubRegistry(TypePool pool)
    {
        Scan(scanner =>
        {
            scanner.AddAllTypes<IService>();
            foreach(var ass in pool.Assemblies)
                scanner.Assembly(ass);
        })
    }
}

public class MySubModule : Module
{
  TypePool _pool;

  public MySubModule(TypePool pool)
  {
    _pool = pool;
  }

  public void RegisterComponents(ContainerBuilder builder)
  {
      var types = _pool.Query().Where( t => t.Implements<IService>());
      builder.RegisterTypes(types)
          .As<IService>();
  }
}
}
Dru Sellers

Ramblings

Categories
Tags


Topics