Question

Is it possible to register a type for all it's implementing interfaces? E.g, I have a:

public class Bow : IWeapon
{

    #region IWeapon Members

    public string Attack()
    {
        return "Shooted with a bow";
    }

    #endregion
}

public class HumanFighter 

{
    private readonly IWeapon weapon = null;
    public HumanFighter(IWeapon weapon)
    {
        this.weapon = weapon;
    }

    public string Fight()
    {

        return this.weapon.Attack();
    }

}

    [Test]
    public void Test2b()
    {
        Container container = new Container();
        container.RegisterSingle<Bow>();
        container.RegisterSingle<HumanFighter>();

        // this would match the IWeapon to the Bow, as it
        // is implemented by Bow
        var humanFighter1 = container.GetInstance<HumanFighter>(); 

        string s = humanFighter1.Fight();
    }
Was it helpful?

Solution

It completely depends on your needs, but typically you need to use the Container's non-generic registration method. You can define your own LINQ queries to query the application's metadata to get the proper types, and register them using the non-generic registration methods. Here's an example:

var weaponsAssembly = typeof(Bow).Assembly;

var registrations =
    from type in weaponsAssembly.GetExportedTypes()
    where type.Namespace.Contains(".Weapons")
    from service in type.GetInterfaces()
    select new { Service = service, Implementation = type };

foreach (var reg in registrations)
{
    container.Register(reg.Service, reg.Implementation);
}

If you need to batch-register a set of implementations, based on a shared generic interface, you can use the RegisterManyForOpenGeneric extension method:

// include the SimpleInjector.Extensions namespace.

container.RegisterManyForOpenGeneric(typeof(IValidator<>),
    typeof(IValidator<>).Assembly);

This will look for all (non-generic) public types in the supplied assembly that implement IValidator<T> and registers each of them by their closed-generic implementation. If an type implements multiple closed-generic versions of IValidator<T>, all versions will be registered. Take a look at the following example:

interface IValidator<T> { }
class MultiVal1 : IValidator<Customer>, IValidator<Order> { }
class MultiVal2 : IValidator<User>, IValidator<Employee> { }

container.RegisterManyForOpenGeneric(typeof(IValidator<>),
    typeof(IValidator<>).Assembly);

Assuming the given interface and class definitions, the shown RegisterManyForOpenGeneric registration is equivalent to the following manual registration:

container.Register<IValidator<Customer>, MultiVal1>();
container.Register<IValidator<Order>, MultiVal1>();
container.Register<IValidator<User>, MultiVal2>();
container.Register<IValidator<Employee>, MultiVal2>();

It would also be easy to add convenient extension methods. Take for instance the following extension method that allows you to register a single implementation by all its implemented interfaces:

public static void RegisterAsImplementedInterfaces<TImpl>(
    this Container container)
{
    foreach (var service in typeof(TImpl).GetInterfaces())
    {
        container.Register(service, typeof(TImpl));
    }
}

It can be used as follows:

container.RegisterAsImplementedInterfaces<Sword>();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top