Skip to content

Generics

Peter Csajtai edited this page Aug 20, 2017 · 21 revisions

Stashbox supports the registration of open generic types:

interface IDrow<TLeftHand, TRightHand> 
{
    //...
}

class Drow<TLeftHand, TRightHand> : IDrow<TLeftHand, TRightHand> 
{
    public Drow(TLeftHand leftHand, TRightHand rightHand)
    {
        //...
    }
}

container.RegisterType(typeof(IDrow<,>), typeof(Drow<,>));
container.RegisterType<Twinkle>();
container.RegisterType<Icingdeath>();

//resolution
var drizzt = container.Resolve<IDrow<Twinkle, Icingdeath>>();

The registered concrete generic types always has a priority over the open generic types.

Checking generic type argument contraints

The dependency selection for generic types is driven by the generic argument constraint matching.

Dependency selection

public interface Constraint { }
public interface IConstraintTest<T> { }
public class ConstraintTest<T> : IConstraintTest<T> { }
public class ConstraintTest2<T> : IConstraintTest<T> where T : Constraint { }
public class ConstraintArgument { }

public class ConstraintTest3
{
    public IConstraintTest<ConstraintArgument> Test { get; set; }
    public ConstraintTest3(IConstraintTest<ConstraintArgument> test) { this.Test = test; }
}

using (var container = new StashboxContainer())
{
    container.RegisterType(typeof(IConstraintTest<>), typeof(ConstraintTest<>));
    container.RegisterType(typeof(IConstraintTest<>), typeof(ConstraintTest2<>));
    container.RegisterType<ConstraintTest3>();
    var inst = container.Resolve<ConstraintTest3>();

    Assert.IsInstanceOfType(inst.Test, typeof(ConstraintTest<ConstraintArgument>));
}

The example above shows that the container will choose the service which's constraint allows the resolution of the given closed generic type.

Collection filters by constraints

using (var container = new StashboxContainer())
{
    container.RegisterType(typeof(IConstraintTest<>), typeof(ConstraintTest<>));
    container.RegisterType(typeof(IConstraintTest<>), typeof(ConstraintTest2<>));

    var inst = container.ResolveAll<IConstraintTest<ConstraintArgument>>().ToArray();
    Assert.AreEqual(1, inst.Length);
}

The example above shows that the container will filter out those services from the returned collection which's constraint doesn't allow the resolution of the given closed generic type.