AbstractHandler
public abstract class AbstractHandler : MarshalByRefObject, IHandler, ISubDependencyResolver, IExposeDependencyInfo, IDisposable
Implements the basis of IHandler
using Castle.Core;
using Castle.Core.Internal;
using Castle.MicroKernel.Context;
using Castle.MicroKernel.Resolvers;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Threading;
namespace Castle.MicroKernel.Handlers
{
[Serializable]
public abstract class AbstractHandler : MarshalByRefObject, IHandler, ISubDependencyResolver, IExposeDependencyInfo, IDisposable
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly ComponentModel model;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private IKernelInternal kernel;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private SimpleThreadSafeSet<DependencyModel> missingDependencies;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private HandlerState state;
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public ComponentModel ComponentModel {
get {
return model;
}
}
public HandlerState CurrentState => state;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
protected IKernelInternal Kernel {
get {
return kernel;
}
}
protected AbstractHandler(ComponentModel model)
{
this.model = model;
}
public abstract bool ReleaseCore(Burden burden);
protected abstract object Resolve(CreationContext context, bool instanceRequired);
public override string ToString()
{
return $"""{model}";
}
public virtual void Dispose()
{
}
public void ObtainDependencyDetails(IDependencyInspector inspector)
{
if (CurrentState != 0) {
SimpleThreadSafeSet<DependencyModel> simpleThreadSafeSet = missingDependencies;
inspector.Inspect(this, (simpleThreadSafeSet != null) ? simpleThreadSafeSet.ToArray() : new DependencyModel[0], Kernel);
}
}
private bool HasCustomParameter(object key)
{
if (key == null)
return false;
return model.CustomDependencies.Contains(key);
}
public virtual void Init(IKernelInternal kernel)
{
if (kernel == null)
throw new ArgumentNullException("kernel");
this.kernel = kernel;
this.kernel.AddedAsChildKernel += OnAddedAsChildKernel;
InitDependencies();
if (AllRequiredDependenciesResolvable()) {
SetNewState(HandlerState.Valid);
DisconnectEvents();
missingDependencies = null;
}
}
protected virtual void InitDependencies()
{
foreach (DependencyModel dependency in ComponentModel.Dependencies) {
AddDependency(dependency);
}
}
public bool IsBeingResolvedInContext(CreationContext context)
{
return context?.IsInResolutionContext(this) ?? false;
}
public virtual bool Release(Burden burden)
{
return ReleaseCore(burden);
}
public object Resolve(CreationContext context)
{
return Resolve(context, true);
}
public virtual bool Supports(Type service)
{
return ComponentModel.Services.Contains(service);
}
public virtual bool SupportsAssignable(Type service)
{
IEnumerable<Type> services = ComponentModel.Services;
TypeInfo typeInfo = service.GetTypeInfo();
return services.Any(typeInfo.IsAssignableFrom);
}
public object TryResolve(CreationContext context)
{
try {
return Resolve(context, false);
} catch (DependencyResolverException exception) {
Kernel.Logger.Warn($"""{ComponentModel.Name}""", exception);
return null;
} catch (HandlerException exception2) {
Kernel.Logger.Warn($"""{ComponentModel.Name}""", exception2);
return null;
}
}
public virtual bool CanResolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency)
{
if (!this.model.HasCustomDependencies)
return false;
if (!HasCustomParameter(dependency.DependencyKey))
return HasCustomParameter(dependency.TargetItemType);
return true;
}
public virtual object Resolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency)
{
if (HasCustomParameter(dependency.DependencyKey))
return model.CustomDependencies[dependency.DependencyKey];
return model.CustomDependencies[dependency.TargetItemType];
}
protected void AddDependency(DependencyModel dependency)
{
dependency.Init(model.ParametersInternal);
if (!AddOptionalDependency(dependency) && !AddResolvableDependency(dependency))
AddMissingDependency(dependency);
}
protected void AddMissingDependency(DependencyModel dependency)
{
SimpleThreadSafeSet<DependencyModel> simpleThreadSafeSet = missingDependencies;
if (simpleThreadSafeSet == null) {
SimpleThreadSafeSet<DependencyModel> simpleThreadSafeSet2 = new SimpleThreadSafeSet<DependencyModel>();
simpleThreadSafeSet = (Interlocked.CompareExchange(ref missingDependencies, simpleThreadSafeSet2, null) ?? simpleThreadSafeSet2);
}
simpleThreadSafeSet.Add(dependency);
if (state != HandlerState.WaitingDependency) {
SetNewState(HandlerState.WaitingDependency);
Kernel.HandlersChanged += this.DependencySatisfied;
}
}
protected bool CanResolvePendingDependencies(CreationContext context)
{
SimpleThreadSafeSet<DependencyModel> simpleThreadSafeSet = missingDependencies;
if (CurrentState == HandlerState.Valid || simpleThreadSafeSet == null)
return true;
DependencyModel[] array = simpleThreadSafeSet.ToArray();
foreach (DependencyModel dependencyModel in array) {
if (dependencyModel.TargetItemType == (Type)null)
return CanProvideDependenciesDynamically(context);
IHandler handler = Kernel.GetHandler(dependencyModel.TargetItemType);
if (handler == this || handler == null)
return CanProvideDependenciesDynamically(context);
}
return true;
}
private bool CanProvideDependenciesDynamically(CreationContext context)
{
if (!context.HasAdditionalArguments)
return kernel.HasComponent(typeof(ILazyComponentLoader));
return true;
}
protected void DependencySatisfied(ref bool stateChanged)
{
SimpleThreadSafeSet<DependencyModel> simpleThreadSafeSet = missingDependencies;
if (simpleThreadSafeSet != null) {
DependencyModel[] array = simpleThreadSafeSet.ToArray();
foreach (DependencyModel dependencyModel in array) {
if (AddResolvableDependency(dependencyModel))
simpleThreadSafeSet.Remove(dependencyModel);
}
if (AllRequiredDependenciesResolvable()) {
SetNewState(HandlerState.Valid);
stateChanged = true;
DisconnectEvents();
missingDependencies = null;
}
}
}
protected void OnAddedAsChildKernel(object sender, EventArgs e)
{
bool stateChanged = false;
DependencySatisfied(ref stateChanged);
}
protected void SetNewState(HandlerState newState)
{
state = newState;
}
private void AddGraphDependency(DependencyModel dependency)
{
IHandler dependencyHandler = GetDependencyHandler(dependency);
if (dependencyHandler != null)
ComponentModel.AddDependent(dependencyHandler.ComponentModel);
}
private IHandler GetDependencyHandler(DependencyModel dependency)
{
if (dependency.ReferencedComponentName != null)
return Kernel.GetHandler(dependency.ReferencedComponentName);
if (dependency.TargetItemType != (Type)null)
return Kernel.GetHandler(dependency.TargetItemType);
return null;
}
private bool AddOptionalDependency(DependencyModel dependency)
{
if (dependency.IsOptional || dependency.HasDefaultValue) {
AddGraphDependency(dependency);
return true;
}
return false;
}
private bool AddResolvableDependency(DependencyModel dependency)
{
if (HasValidComponentFromResolver(dependency)) {
AddGraphDependency(dependency);
return true;
}
return false;
}
private bool AllRequiredDependenciesResolvable()
{
SimpleThreadSafeSet<DependencyModel> simpleThreadSafeSet = missingDependencies;
if (simpleThreadSafeSet == null)
return true;
DependencyModel[] array = simpleThreadSafeSet.ToArray();
if (array.Length == 0)
return true;
List<ConstructorDependencyModel> list = array.OfType<ConstructorDependencyModel>().ToList();
if (array.Length != list.Count)
return false;
int num = (from d in list
select d.Constructor).Distinct().Count();
return model.Constructors.Count > num;
}
private void DisconnectEvents()
{
Kernel.HandlersChanged -= this.DependencySatisfied;
Kernel.AddedAsChildKernel -= OnAddedAsChildKernel;
}
private bool HasValidComponentFromResolver(DependencyModel dependency)
{
return Kernel.Resolver.CanResolve(CreationContext.ForDependencyInspection(this), this, model, dependency);
}
}
}