Skip to content

Generics

Peter Csajtai edited this page Jun 11, 2019 · 21 revisions

With stashbox you have the option to register open generic types, which gives you the flexibility of choosing the closed generic parameter later at resolution time.

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

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

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

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

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

Dependency selection by contraints

The dependencies of the generic services are choosed by matching to their generic argument constraints.

interface IConstraint { }
interface IConstraint1 { }
interface IConstraintTest<T> { }
class ConstraintTest<T> : IConstraintTest<T> where T : IConstraint { }
class ConstraintTest1<T> : IConstraintTest<T> where T : IConstraint1 { }
class ConstraintArgument : IConstraint1 { }

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

     var inst = container.Resolve<IConstraintTest<ConstraintArgument>>();
     Assert.IsInstanceOfType(inst, typeof(ConstraintTest1<ConstraintArgument>));
}

The example above shows that the container chooses ConstraintTest1 because its generic argument constraint matches to the interface implemented by the requested ConstraintArgument.

Collection filters by constraints

using (var container = new StashboxContainer())
{
    container.Register(typeof(IConstraintTest<>), typeof(ConstraintTest<>));
    container.Register(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 whichs constraint doesn't allow the resolution of the given closed generic type.