DependencyInspector
using Castle.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Castle.MicroKernel.Handlers
{
public class DependencyInspector : IDependencyInspector
{
private readonly HashSet<IHandler> handlersChecked = new HashSet<IHandler>();
private readonly StringBuilder message;
public string Message => message.ToString();
public DependencyInspector(StringBuilder message)
{
this.message = message;
}
public void Inspect(IHandler handler, DependencyModel[] missingDependencies, IKernel kernel)
{
if (handlersChecked.Add(handler)) {
HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
message.AppendLine();
message.AppendFormat("'{0}' is waiting for the following dependencies:", handler.ComponentModel.Name);
message.AppendLine();
foreach (DependencyModel dependencyModel in missingDependencies) {
if (dependencyModel.ReferencedComponentName != null) {
if (hashSet.Add(dependencyModel.ReferencedComponentName))
InspectServiceOverrideDependency(dependencyModel, kernel);
} else if (dependencyModel.IsPrimitiveTypeDependency) {
InspectParameterDependency(dependencyModel);
} else {
InspectServiceDependency(handler, dependencyModel, kernel);
}
}
}
}
private void InspectParameterDependency(DependencyModel dependency)
{
string dependencyKey = dependency.DependencyKey;
message.AppendFormat("- Parameter '{0}' which was not provided. Did you forget to set the dependency?", dependencyKey);
message.AppendLine();
}
private void InspectServiceDependency(IHandler inspectingHandler, DependencyModel dependency, IKernel kernel)
{
Type targetItemType = dependency.TargetItemType;
IHandler handler = kernel.GetHandler(targetItemType);
if (handler == null) {
message.AppendFormat("- Service '{0}' which was not registered.", targetItemType.FullName ?? targetItemType.Name);
message.AppendLine();
} else if (handler == inspectingHandler) {
IHandler[] handlers = kernel.GetHandlers(targetItemType);
message.AppendFormat("- Service '{0}' which points back to the component itself.", targetItemType.FullName ?? targetItemType.Name);
message.AppendLine();
message.Append("A dependency cannot be satisfied by the component itself, did you forget to ");
if (handlers.Length == 1)
message.AppendLine("register other components for this service?");
else {
message.AppendLine("make this a service override and point explicitly to a different component exposing this service?");
message.AppendLine();
message.Append("The following components also expose the service, but none of them can be resolved:");
foreach (IHandler item in from maybeDecoratedHandler in handlers
where maybeDecoratedHandler != inspectingHandler
select maybeDecoratedHandler) {
IExposeDependencyInfo exposeDependencyInfo = item as IExposeDependencyInfo;
if (exposeDependencyInfo != null)
exposeDependencyInfo.ObtainDependencyDetails(this);
else {
message.AppendLine();
message.AppendFormat("'{0}' is registered and is matching the required service, but cannot be resolved.", item.ComponentModel.Name);
}
}
}
} else {
message.AppendFormat("- Service '{0}' which was registered but is also waiting for dependencies.", handler.ComponentModel.Name);
(handler as IExposeDependencyInfo)?.ObtainDependencyDetails(this);
}
}
private void InspectServiceOverrideDependency(DependencyModel dependency, IKernel kernel)
{
string referencedComponentName = dependency.ReferencedComponentName;
IHandler handler = kernel.GetHandler(referencedComponentName);
if (handler == null) {
message.AppendFormat("- Component '{0}' (via override) which was not found. Did you forget to register it or misspelled the name? If the component is registered and override is via type make sure it doesn't have non-default name assigned explicitly or override the dependency via name.", referencedComponentName);
message.AppendLine();
} else {
message.AppendFormat("- Component '{0}' (via override) which was registered but is also waiting for dependencies.", referencedComponentName);
message.AppendLine();
(handler as IExposeDependencyInfo)?.ObtainDependencyDetails(this);
}
}
}
}