Dru Sellers

Type Pool

326 words ยท 2 minute read

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.

{{< highlight csharp >}} 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>());
    }
}

} {{< /highlight >}}

{{< highlight csharp >}}

var typePool = new TypePool(typeof(MarkerType).Assembly); var settingTypes = typePool.Query().Where(t=>t.Name.EndsWith("Settings"));

{{< /highlight >}}

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.

{{< highlight csharp >}}

public class MySubRegistry : Registry { public MySubRegistry(TypePool pool) { Scan(scanner => { scanner.AddAllTypes(); 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()); builder.RegisterTypes(types) .As(); } } } {{< /highlight >}}