Skip to content

Resolvers

Peter Csajtai edited this page Feb 16, 2017 · 29 revisions

Stashbox internally maintains a resolution graph between the registered services with a Resolver instance assigned to each of them.

For faster resolution it also maintains an internal Expression tree through all the dependencies.

Stashbox contains three pre-defined Resolvers:

  • ContainerResolver: It mainly uses the container itself for resolving dependencies.
  • EnumerableResolver: It resolves every registered type of a service as an IEnumerable or array.
  • LazyResolver: It can resolve services registered into the container wrapped by a Lazy<>.
  • FuncResolver: It can resolve services wrapped into a Func<> delegate.
  • DefaultValueResolver: It can resolve optional and default values.
  • UnknownTypeResolver: It can resolve services which are not registered into the container.

You can also specify a special rule to resolve services and extend the functionality of Stashbox by registering a custom Resolver implementation into it:

class MagicalWeaponResolver : Resolver
{
	 public MagicalWeaponResolver(IContainerContext containerContext, TypeInformation typeInfo)
            : base(containerContext, typeInfo)
        { 
        	//The TypeInformation parameters holds information about the type which was actually requested from the container.
        }
		
    public override Expression GetExpression(ResolutionInfo resolutionInfo)
    {
        //The ResolutionInfo parameter holds information about the current resolution context (Circular dependency barrier and parameter expressions)
    }

    public override Type WrappedType => ...; //If the resolver activates a generic wrapper, this property should return with the wrapped type.

    public override bool CanUseForEnumerableArgumentResolution => ...; //Should return true, if the resolver can be used for enumerable argument resolution e.g. the enumerable
    																   //argument is a wrapped generic type which can be resolved by this resolver, otherwise false.

    public override Expression[] GetEnumerableArgumentExpressions(ResolutionInfo resolutionInfo)
    {
    	//If the CanUseForEnumerableArgumentResolution is set to true, the EnumerableResolver will call this method to collect the expressions of the enumerable items.
    }
}

##Resolver registration

container.RegisterResolver((context, typeInfo) => Gauntlgrym.CanProduce(typeInfo), (context, typeInfo) => new MagicalWeaponResolver(context, typeInfo));

The first parameter is a predicate delegate which can decide the actual type can be resolved by the resolver or not. The second parameter is a factory delegate for creating a resolver instance.

Stashbox will choose from the resolvers to accomplish the current resolution request in the following order:

  1. ContainerResolver
  2. EnumerableResolver
  3. LazyResolver
  4. FuncResolver
  5. DefaultValueResolver
  6. UnknownTypeResolver
  7. Custom, external resolvers
  8. Parent container resolvers