Skip to content
Talljoe edited this page Mar 14, 2011 · 9 revisions

The internals of Ninject are broken up into components that are wired together using a lightweight Inversion of Control container (yes, Ninject is actually two Dependency Injection frameworks). This allows custom behavior to be inserted into the resolution pipeline. The components that Ninject use are all accessed from the Components property off of IKernel. These components are generally loaded from a subclass of KernelBase such as StandardKernel but can also be added externally.

This is StandardKernel.AddComponents() as it exists in version 2.2:

Components.Add<IPlanner, Planner>();
Components.Add<IPlanningStrategy, ConstructorReflectionStrategy>();
Components.Add<IPlanningStrategy, PropertyReflectionStrategy>();
Components.Add<IPlanningStrategy, MethodReflectionStrategy>();

Components.Add<ISelector, Selector>();
Components.Add<IConstructorScorer, StandardConstructorScorer>();
Components.Add<IInjectionHeuristic, StandardInjectionHeuristic>();

Components.Add<IPipeline, Pipeline>();
Components.Add<IActivationStrategy, ActivationCacheStrategy>();
Components.Add<IActivationStrategy, PropertyInjectionStrategy>();
Components.Add<IActivationStrategy, MethodInjectionStrategy>();
Components.Add<IActivationStrategy, InitializableStrategy>();
Components.Add<IActivationStrategy, StartableStrategy>();
Components.Add<IActivationStrategy, BindingActionStrategy>();
Components.Add<IActivationStrategy, DisposableStrategy>();

Components.Add<IBindingResolver, StandardBindingResolver>();
Components.Add<IBindingResolver, OpenGenericBindingResolver>();

Components.Add<IMissingBindingResolver, DefaultValueBindingResolver>();
Components.Add<IMissingBindingResolver, SelfBindingResolver>();

#if !NO_LCG
if (!Settings.UseReflectionBasedInjection)
{
  Components.Add<IInjectorFactory, DynamicMethodInjectorFactory>();
}
else
#endif
{
  Components.Add<IInjectorFactory, ReflectionInjectorFactory>();
}

Components.Add<ICache, Cache>();
Components.Add<IActivationCache, ActivationCache>();
Components.Add<ICachePruner, GarbageCollectionCachePruner>();

#if !NO_ASSEMBLY_SCANNING
Components.Add<IModuleLoader, ModuleLoader>();
Components.Add<IModuleLoaderPlugin, CompiledModuleLoaderPlugin>();
#endif

Component Extension Points

IBindingResolver

IMissingBindingResolver

IPipeline

IActivationStrategy

ISelector

IInjectionHeuristic

IConstructorScorer

IPlanner

IPlanningStrategy

IInjectorFactory

ICache

IActivationCache

ICachePruner

IModuleLoader

IModuleLoaderPlugin

KernelBase Extension Points

You can also affect the behavior of Ninject by deriving from KernelBase itself and overriding important functionality. Note that this is more brittle than the interfaces as often times core functionality is rewritten as components and this can make your changes incompatibile with future versions.

Inject

/// <summary>
/// Injects the specified existing instance, without managing its lifecycle.
/// </summary>
/// <param name="instance">The instance to inject.</param>
/// <param name="parameters">The parameters to pass to the request.</param>
void Inject(object instance, params IParameter[] parameters)

Release

/// <summary>
/// Deactivates and releases the specified instance if it is currently managed by Ninject.
/// </summary>
/// <param name="instance">The instance to release.</param>
/// <returns><see langword="True"/> if the instance was found and released; otherwise <see langword="false"/>.</returns>
bool Release(object instance)

CanResolve

/// <summary>
/// Determines whether the specified request can be resolved.
/// </summary>
/// <param name="request">The request.</param>
/// <returns><c>True</c> if the request can be resolved; otherwise, <c>false</c>.</returns>
bool CanResolve(IRequest request)

Resolve

/// <summary>
/// Resolves instances for the specified request. The instances are not actually resolved
/// until a consumer iterates over the enumerator.
/// </summary>
/// <param name="request">The request to resolve.</param>
/// <returns>An enumerator of instances that match the request.</returns>
IEnumerable<object> Resolve(IRequest request)

CreateRequest

/// <summary>
/// Creates a request for the specified service.
/// </summary>
/// <param name="service">The service that is being requested.</param>
/// <param name="constraint">The constraint to apply to the bindings to determine if they match the request.</param>
/// <param name="parameters">The parameters to pass to the resolution.</param>
/// <param name="isOptional"><c>True</c> if the request is optional; otherwise, <c>false</c>.</param>
/// <param name="isUnique"><c>True</c> if the request should return a unique result; otherwise, <c>false</c>.</param>
/// <returns>The created request.</returns>
IRequest CreateRequest(Type service, Func<IBindingMetadata, bool> constraint, IEnumerable<IParameter> parameters, bool isOptional, bool isUnique)

BeginBlock

/// <summary>
/// Begins a new activation block, which can be used to deterministically dispose resolved instances.
/// </summary>
/// <returns>The new activation block.</returns>
IActivationBlock BeginBlock()

GetBindings

/// <summary>
/// Gets the bindings registered for the specified service.
/// </summary>
/// <param name="service">The service in question.</param>
/// <returns>A series of bindings that are registered for the service.</returns>
IEnumerable<IBinding> GetBindings(Type service)

It is preferable to create a component that implements IBindingResolver.

GetBindingPrecedenceComparer

/// <summary>
/// Returns an IComparer that is used to determine resolution precedence.
/// </summary>
/// <returns>An IComparer that is used to determine resolution precedence.</returns>
IComparer<IBinding> GetBindingPrecedenceComparer()

This method returns an IComparer that decides the precendence of bindings. The default is to prefer explicit bindings over implicit and contextual bindings over unconditional bindings.

SatifiesRequest

/// <summary>
/// Returns a predicate that can determine if a given IBinding matches the request.
/// </summary>
/// <param name="request">The request/</param>
/// <returns>A predicate that can determine if a given IBinding matches the request.</returns>
Func<IBinding, bool> SatifiesRequest(IRequest request)

HandleMissingBinding

/// <summary>
/// Attempts to handle a missing binding for a request.
/// </summary>
/// <param name="request">The request.</param>
/// <returns><c>True</c> if the missing binding can be handled; otherwise <c>false</c>.</returns>
bool HandleMissingBinding(IRequest request)

It is preferable to create a component that implements IMissingBindingResolver.

CreateContext

/// <summary>
/// Creates a context for the specified request and binding.
/// </summary>
/// <param name="request">The request.</param>
/// <param name="binding">The binding.</param>
/// <returns>The created context.</returns>
IContext CreateContext(IRequest request, IBinding binding)