Skip to content

Building an IMissingBindingResolver Component

Remo Gloor edited this page Feb 23, 2012 · 3 revisions

IMissingBindingResolver components are used to find bindings when no other bindings exist. Whereas an IBindingResolver component works against the bindings already registered an IMissingBindingResolver component can create new bindings to handle the request. They also have access to the entire request, not just the service being requested, which leads to more powerful scenarios.

Let’s take a quick look at the SelfBindingResolver in Ninject.

public class SelfBindingResolver : NinjectComponent, IMissingBindingResolver
{
    /// <summary>
    /// Returns any bindings from the specified collection that match the specified service.
    /// </summary>
    /// <param name="bindings">The multimap of all registered bindings.</param>
    /// <param name="request">The service in question.</param>
    /// <returns>The series of matching bindings.</returns>
    public IEnumerable<IBinding> Resolve(Multimap<Type, IBinding> bindings, IRequest request)
    {
        var service = request.Service;
        if (!TypeIsSelfBindable(service))
        {
            return Enumerable.Empty<IBinding>();
        }
        return new[] {
            new Binding(service)
            {
                ProviderCallback = StandardProvider.GetCreationCallback(service)
            }
        };
    }

    /// <summary>
    /// Returns a value indicating whether the specified service is self-bindable.
    /// </summary>
    /// <param name="service">The service.</param>
    /// <returns><see langword="True"/> if the type is self-bindable; otherwise <see langword="false"/>.</returns>
    protected virtual bool TypeIsSelfBindable(Type service)
    {
        return !service.IsInterface
               && !service.IsAbstract
               && !service.IsValueType
               && service != typeof(string)
               && !service.ContainsGenericParameters;
    }
}

This component is pretty straight forward. If the type being requested is not capable of being self-bound it returns an empty collection. If it can be self-bound it returns a new binding. When the Kernel receives the new binding it marks it as implicit and adds it to the map (see binding precedence for more information on implicit bindings).

Also note that the concept of what is “self-bindable” is extensible. You can derive from SelfBindingResolver and override TypeIsSelfBindable to add new criteria or explicit exclude certain types from being self-bound.

Creating A New Missing-Binding Resolver

TODO