BasedOnDescriptor
Describes how to register a group of related types.
using Castle.Core;
using Castle.MicroKernel.Lifestyle.Scoped;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
namespace Castle.MicroKernel.Registration
{
public class BasedOnDescriptor : IRegistration
{
private readonly List<Type> potentialBases;
private Action<ComponentRegistration> configuration;
private readonly FromDescriptor from;
private readonly ServiceDescriptor service;
private Predicate<Type> ifFilter;
private Predicate<Type> unlessFilter;
public ServiceDescriptor WithService => service;
internal BasedOnDescriptor(IEnumerable<Type> basedOn, FromDescriptor from, Predicate<Type> additionalFilters)
{
potentialBases = basedOn.ToList();
this.from = from;
service = new ServiceDescriptor(this);
If(additionalFilters);
}
public FromDescriptor AllowMultipleMatches()
{
return from.AllowMultipleMatches();
}
[Obsolete("Calling this method resets registration. If that's what you want, start anew, with Classes.FromAssembly..")]
[EditorBrowsable(EditorBrowsableState.Never)]
public BasedOnDescriptor BasedOn<T>()
{
return from.BasedOn<T>();
}
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("Calling this method resets registration. If that's what you want, start anew, with Classes.FromAssembly...")]
public BasedOnDescriptor BasedOn(Type basedOn)
{
return from.BasedOn(basedOn);
}
public BasedOnDescriptor OrBasedOn(Type basedOn)
{
potentialBases.Add(basedOn);
return this;
}
public BasedOnDescriptor Configure(Action<ComponentRegistration> configurer)
{
configuration = (Action<ComponentRegistration>)Delegate.Combine(configuration, configurer);
return this;
}
public BasedOnDescriptor ConfigureFor<TComponentImplementationType>(Action<ComponentRegistration> configurer)
{
return ConfigureIf((ComponentRegistration r) => typeof(TComponentImplementationType).IsAssignableFrom(((ComponentRegistration<object>)r).Implementation), configurer);
}
public BasedOnDescriptor ConfigureIf(Predicate<ComponentRegistration> condition, Action<ComponentRegistration> configurer)
{
configuration = (Action<ComponentRegistration>)Delegate.Combine(configuration, (Action<ComponentRegistration>)delegate(ComponentRegistration r) {
if (condition(r))
configurer(r);
});
return this;
}
public BasedOnDescriptor ConfigureIf(Predicate<ComponentRegistration> condition, Action<ComponentRegistration> configurerWhenTrue, Action<ComponentRegistration> configurerWhenFalse)
{
configuration = (Action<ComponentRegistration>)Delegate.Combine(configuration, (Action<ComponentRegistration>)delegate(ComponentRegistration r) {
if (condition(r))
configurerWhenTrue(r);
else
configurerWhenFalse(r);
});
return this;
}
public BasedOnDescriptor If(Predicate<Type> ifFilter)
{
this.ifFilter = (Predicate<Type>)Delegate.Combine(this.ifFilter, ifFilter);
return this;
}
public BasedOnDescriptor Unless(Predicate<Type> unlessFilter)
{
this.unlessFilter = (Predicate<Type>)Delegate.Combine(this.unlessFilter, unlessFilter);
return this;
}
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("Calling this method resets registration. If that's what you want, start anew, with Classes.FromAssembly...")]
public BasedOnDescriptor Where(Predicate<Type> accepted)
{
return from.Where(accepted);
}
public BasedOnDescriptor WithServiceAllInterfaces()
{
return WithService.AllInterfaces();
}
public BasedOnDescriptor WithServiceBase()
{
return WithService.Base();
}
public BasedOnDescriptor WithServiceDefaultInterfaces()
{
return WithService.DefaultInterfaces();
}
public BasedOnDescriptor WithServiceFirstInterface()
{
return WithService.FirstInterface();
}
public BasedOnDescriptor WithServiceFromInterface(Type implements)
{
return WithService.FromInterface(implements);
}
public BasedOnDescriptor WithServiceFromInterface()
{
return WithService.FromInterface();
}
public BasedOnDescriptor WithServiceSelect(ServiceDescriptor.ServiceSelector selector)
{
return WithService.Select(selector);
}
public BasedOnDescriptor WithServiceSelf()
{
return WithService.Self();
}
public BasedOnDescriptor LifestyleCustom(Type customLifestyleType)
{
return Configure(delegate(ComponentRegistration c) {
c.LifestyleCustom(customLifestyleType);
});
}
public BasedOnDescriptor LifestyleCustom<TLifestyleManager>() where TLifestyleManager : ILifestyleManager, new
{
return Configure(delegate(ComponentRegistration c) {
c.LifestyleCustom<TLifestyleManager>();
});
}
public BasedOnDescriptor LifestylePerThread()
{
return Configure(delegate(ComponentRegistration c) {
c.LifestylePerThread();
});
}
public BasedOnDescriptor LifestyleScoped()
{
return Configure(delegate(ComponentRegistration c) {
c.LifestyleScoped(null);
});
}
public BasedOnDescriptor LifestyleScoped(Type scopeAccessorType)
{
return Configure(delegate(ComponentRegistration c) {
c.LifestyleScoped(scopeAccessorType);
});
}
public BasedOnDescriptor LifestyleScoped<TScopeAccessor>() where TScopeAccessor : IScopeAccessor, new
{
return Configure(delegate(ComponentRegistration c) {
c.LifestyleScoped<TScopeAccessor>();
});
}
public BasedOnDescriptor LifestyleBoundTo<TBaseForRoot>() where TBaseForRoot : class
{
return Configure(delegate(ComponentRegistration c) {
c.LifestyleBoundTo<TBaseForRoot>();
});
}
public BasedOnDescriptor LifestyleBoundToNearest<TBaseForRoot>() where TBaseForRoot : class
{
return Configure(delegate(ComponentRegistration c) {
c.LifestyleBoundToNearest<TBaseForRoot>();
});
}
public BasedOnDescriptor LifestylePerWebRequest()
{
return Configure(delegate(ComponentRegistration c) {
c.LifestylePerWebRequest();
});
}
public BasedOnDescriptor LifestylePooled(int? initialSize = default(int?), int? maxSize = default(int?))
{
return Configure(delegate(ComponentRegistration c) {
c.LifestylePooled(initialSize, maxSize);
});
}
public BasedOnDescriptor LifestyleSingleton()
{
return Configure(delegate(ComponentRegistration c) {
c.LifestyleSingleton();
});
}
public BasedOnDescriptor LifestyleTransient()
{
return Configure(delegate(ComponentRegistration c) {
c.LifestyleTransient();
});
}
public BasedOnDescriptor WithServices(IEnumerable<Type> types)
{
return WithService.Select(types);
}
public BasedOnDescriptor WithServices(params Type[] types)
{
return WithService.Select(types);
}
protected virtual bool Accepts(Type type, out Type[] baseTypes)
{
if (IsBasedOn(type, out baseTypes) && ExecuteIfCondition(type))
return !ExecuteUnlessCondition(type);
return false;
}
protected bool ExecuteIfCondition(Type type)
{
if (ifFilter == null)
return true;
Delegate[] invocationList = ifFilter.GetInvocationList();
for (int i = 0; i < invocationList.Length; i++) {
Predicate<Type> predicate = (Predicate<Type>)invocationList[i];
if (!predicate(type))
return false;
}
return true;
}
protected bool ExecuteUnlessCondition(Type type)
{
if (unlessFilter == null)
return false;
Delegate[] invocationList = unlessFilter.GetInvocationList();
for (int i = 0; i < invocationList.Length; i++) {
Predicate<Type> predicate = (Predicate<Type>)invocationList[i];
if (predicate(type))
return true;
}
return false;
}
protected bool IsBasedOn(Type type, out Type[] baseTypes)
{
List<Type> list = new List<Type>();
foreach (Type potentialBasis in potentialBases) {
if (potentialBasis.IsAssignableFrom(type))
list.Add(potentialBasis);
else if (potentialBasis.IsGenericTypeDefinition) {
if (potentialBasis.IsInterface && IsBasedOnGenericInterface(type, potentialBasis, out baseTypes))
list.AddRange(baseTypes);
if (IsBasedOnGenericClass(type, potentialBasis, out baseTypes))
list.AddRange(baseTypes);
}
}
baseTypes = list.Distinct().ToArray();
return baseTypes.Length > 0;
}
internal bool TryRegister(Type type, IKernel kernel)
{
if (!Accepts(type, out Type[] baseTypes))
return false;
CastleComponentAttribute defaultsFor = CastleComponentAttribute.GetDefaultsFor(type);
ICollection<Type> services = service.GetServices(type, baseTypes);
if (services.Count == 0 && defaultsFor.Services.Length > 0)
services = defaultsFor.Services;
ComponentRegistration componentRegistration = Component.For(services);
componentRegistration.ImplementedBy(type);
if (configuration != null)
configuration(componentRegistration);
if (string.IsNullOrEmpty(componentRegistration.Name) && !string.IsNullOrEmpty(defaultsFor.Name))
componentRegistration.Named(defaultsFor.Name);
else
componentRegistration.RegisterOptionally();
kernel.Register(componentRegistration);
return true;
}
private static bool IsBasedOnGenericClass(Type type, Type basedOn, out Type[] baseTypes)
{
while (type != (Type)null) {
if (type.IsGenericType && type.GetGenericTypeDefinition() == basedOn) {
baseTypes = new Type[1] {
type
};
return true;
}
type = type.BaseType;
}
baseTypes = null;
return false;
}
private static bool IsBasedOnGenericInterface(Type type, Type basedOn, out Type[] baseTypes)
{
List<Type> list = new List<Type>(4);
Type[] interfaces = type.GetInterfaces();
foreach (Type type2 in interfaces) {
if (type2.IsGenericType && type2.GetGenericTypeDefinition() == basedOn) {
if (type2.ReflectedType == (Type)null && type2.ContainsGenericParameters)
list.Add(type2.GetGenericTypeDefinition());
else
list.Add(type2);
}
}
baseTypes = list.ToArray();
return baseTypes.Length > 0;
}
void IRegistration.Register(IKernelInternal kernel)
{
((IRegistration)from).Register(kernel);
}
}
}