<PackageReference Include="Castle.Windsor" Version="3.1.0" />

DefaultGenericHandler

using Castle.Core; using Castle.Core.Internal; using Castle.DynamicProxy; using Castle.MicroKernel.ComponentActivator; using Castle.MicroKernel.Context; using System; using System.Collections; using System.Collections.Generic; using System.Linq; namespace Castle.MicroKernel.Handlers { public class DefaultGenericHandler : AbstractHandler { private readonly IGenericImplementationMatchingStrategy implementationMatchingStrategy; private readonly IGenericServiceStrategy serviceStrategy; private readonly SimpleThreadSafeDictionary<Type, IHandler> type2SubHandler = new SimpleThreadSafeDictionary<Type, IHandler>(); public IGenericImplementationMatchingStrategy ImplementationMatchingStrategy => implementationMatchingStrategy; public IGenericServiceStrategy ServiceStrategy => serviceStrategy; public DefaultGenericHandler(ComponentModel model, IGenericImplementationMatchingStrategy implementationMatchingStrategy, IGenericServiceStrategy serviceStrategy) : base(model) { this.implementationMatchingStrategy = implementationMatchingStrategy; this.serviceStrategy = serviceStrategy; } public override void Dispose() { IHandler[] array = type2SubHandler.EjectAllValues(); IHandler[] array2 = array; foreach (IHandler handler in array2) { (handler as IDisposable)?.Dispose(); } } public override bool ReleaseCore(Burden burden) { Type unproxiedType = ProxyUtil.GetUnproxiedType(burden.Instance); IHandler subHandler = GetSubHandler(CreationContext.CreateEmpty(), unproxiedType); return subHandler.Release(burden); } public override bool Supports(Type service) { if (base.Supports(service)) return true; if (type2SubHandler.Contains(service)) return true; if (service.IsGenericType && !service.IsGenericTypeDefinition) { Type genericTypeDefinition = service.GetGenericTypeDefinition(); if (!base.Supports(genericTypeDefinition)) return false; if (serviceStrategy != null) return serviceStrategy.Supports(service, base.ComponentModel); return true; } return false; } public override bool SupportsAssignable(Type service) { if (base.SupportsAssignable(service)) return true; if (!service.IsGenericType || service.IsGenericTypeDefinition) return false; Type[] serviceArguments = service.GetGenericArguments(); return base.ComponentModel.Services.Any((Type s) => SupportsAssignable(service, s, serviceArguments)); } protected virtual Type[] AdaptServices(CreationContext context, Type closedImplementationType) { Type[] array = base.ComponentModel.Services.ToArray(); if (array.Length == 1 && (object)array[0] == context.RequestedType.GetGenericTypeDefinition()) return new Type[1] { context.RequestedType }; List<Type> list = new List<Type>(array.Length); int num = AdaptClassServices(closedImplementationType, list, array); if (num == array.Length - 1) return list.ToArray(); AdaptInterfaceServices(closedImplementationType, list, array, num); if (list.Count == 0) return new Type[1] { context.RequestedType }; return list.ToArray(); } protected virtual IHandler BuildSubHandler(CreationContext context, Type closedImplementationType) { ComponentModel componentModel = base.Kernel.ComponentModelBuilder.BuildModel(base.ComponentModel.ComponentName, AdaptServices(context, closedImplementationType), closedImplementationType, GetExtendedProperties()); CloneParentProperties(componentModel); IKernelInternal kernel = base.Kernel; bool isMetaHandler = true; return kernel.AddCustomComponent(componentModel, isMetaHandler); } protected IHandler GetSubHandler(CreationContext context, Type genericType) { return type2SubHandler.GetOrAdd(genericType, (Type t) => BuildSubHandler(context, t)); } protected override void InitDependencies() { IDependencyAwareActivator dependencyAwareActivator = base.Kernel.CreateComponentActivator(base.ComponentModel) as IDependencyAwareActivator; if (dependencyAwareActivator == null || !dependencyAwareActivator.CanProvideRequiredDependencies(base.ComponentModel)) base.InitDependencies(); } protected override object Resolve(CreationContext context, bool instanceRequired) { Type closedImplementationType = GetClosedImplementationType(context, instanceRequired); if ((object)closedImplementationType == null) return null; IHandler subHandler = GetSubHandler(context, closedImplementationType); using (context.EnterResolutionContext(this, false, false)) try { return subHandler.Resolve(context); } catch (GenericHandlerTypeMismatchException innerException) { throw new HandlerException($"""{base.ComponentModel.Name}""", base.ComponentModel.ComponentName, innerException); } } protected bool SupportsAssignable(Type service, Type modelService, Type[] serviceArguments) { if (!modelService.IsGenericTypeDefinition || modelService.GetGenericArguments().Length != serviceArguments.Length) return false; Type type = modelService.TryMakeGenericType(serviceArguments); if ((object)type == null) return false; if (!service.IsAssignableFrom(type)) return false; if (ServiceStrategy != null && !ServiceStrategy.Supports(type, base.ComponentModel)) return false; return true; } private void CloneParentProperties(ComponentModel newModel) { newModel.LifestyleType = base.ComponentModel.LifestyleType; foreach (InterceptorReference interceptor in base.ComponentModel.Interceptors) { newModel.Interceptors.AddIfNotInCollection(interceptor); } if (base.ComponentModel.HasCustomDependencies) { IDictionary customDependencies = newModel.CustomDependencies; IDictionaryEnumerator enumerator2 = base.ComponentModel.CustomDependencies.GetEnumerator(); try { while (enumerator2.MoveNext()) { DictionaryEntry dictionaryEntry = (DictionaryEntry)enumerator2.Current; customDependencies.Add(dictionaryEntry.Key, dictionaryEntry.Value); } } finally { (enumerator2 as IDisposable)?.Dispose(); } } } private Type GetClosedImplementationType(CreationContext context, bool instanceRequired) { Type[] genericArguments = GetGenericArguments(context); try { return base.ComponentModel.Implementation.MakeGenericType(genericArguments); } catch (ArgumentNullException) { if (implementationMatchingStrategy == null) throw; throw new HandlerException(string.Format("Custom {0} ({1}) didn't select any generic parameters for implementation type of component '{2}'. This usually signifies bug in the {0}.", typeof(IGenericImplementationMatchingStrategy).Name, implementationMatchingStrategy, base.ComponentModel.Name), base.ComponentModel.ComponentName); } catch (ArgumentException innerException) { if (instanceRequired) { Type[] genericArguments2 = base.ComponentModel.Implementation.GetGenericArguments(); if (genericArguments2.Length > genericArguments.Length) { string str = $"""{context.RequestedType}""{context.GenericArguments.Length}""{base.ComponentModel.Implementation}""{genericArguments2.Length}""{Environment.NewLine}"""; str = ((implementationMatchingStrategy != null) ? (str + string.Format("{0}This is most likely a bug in the {1} implementation this component uses ({2}).{0}Please consut the documentation for examples of how to implement it properly.", Environment.NewLine, typeof(IGenericImplementationMatchingStrategy).Name, implementationMatchingStrategy)) : (str + string.Format("{0}You can instruct Windsor which types it should use to close this generic component by supplying an implementation of {1}.{0}Please consut the documentation for examples of how to do that.", Environment.NewLine, typeof(IGenericImplementationMatchingStrategy).Name))); throw new HandlerException(str, base.ComponentModel.ComponentName, innerException); } string[] array = (from t in genericArguments.Where(delegate(Type a) { if (!a.IsPointer && !a.IsByRef) return (object)a == typeof(void); return true; }) select t.FullName).ToArray(); if (array.Length > 0) { string str = string.Format("The following types provided as generic parameters are not legal: {0}. This is most likely a bug in your code.", string.Join(", ", array)); throw new HandlerException(str, base.ComponentModel.ComponentName, innerException); } throw new GenericHandlerTypeMismatchException(genericArguments, base.ComponentModel, this); } return null; } } private IDictionary GetExtendedProperties() { IDictionary dictionary = base.ComponentModel.ExtendedProperties; if (dictionary != null && dictionary.Count > 0) dictionary = new Arguments(dictionary); return dictionary; } private Type[] GetGenericArguments(CreationContext context) { if (implementationMatchingStrategy == null) return context.GenericArguments; return implementationMatchingStrategy.GetGenericArguments(base.ComponentModel, context) ?? context.GenericArguments; } private static int AdaptClassServices(Type closedImplementationType, List<Type> closedServices, Type[] openServices) { int i = 0; IDictionary<Type, Type> genericDefinitionToClass = null; for (; i < openServices.Length && openServices[i].IsClass; i++) { Type type = openServices[i]; if (type.IsGenericTypeDefinition) { EnsureClassMappingInitialized(closedImplementationType, ref genericDefinitionToClass); if (genericDefinitionToClass.TryGetValue(type, out Type value)) closedServices.Add(value); } else closedServices.Add(type); } return i; } private static void AdaptInterfaceServices(Type closedImplementationType, List<Type> closedServices, Type[] openServices, int index) { IDictionary<Type, Type> genericDefinitionToInterface = null; while (index < openServices.Length) { Type type = openServices[index]; if (type.IsGenericTypeDefinition) { EnsureInterfaceMappingInitialized(closedImplementationType, ref genericDefinitionToInterface); if (genericDefinitionToInterface.TryGetValue(type, out Type value)) closedServices.Add(value); } else closedServices.Add(type); index++; } } private static void EnsureClassMappingInitialized(Type closedImplementationType, ref IDictionary<Type, Type> genericDefinitionToClass) { if (genericDefinitionToClass == null) { genericDefinitionToClass = new Dictionary<Type, Type>(); Type type = closedImplementationType; while ((object)type != typeof(object)) { if (type.IsGenericType) genericDefinitionToClass.Add(type.GetGenericTypeDefinition(), type); type = type.BaseType; } } } private static void EnsureInterfaceMappingInitialized(Type closedImplementationType, ref IDictionary<Type, Type> genericDefinitionToInterface) { if (genericDefinitionToInterface == null) genericDefinitionToInterface = (from i in closedImplementationType.GetInterfaces() where i.IsGenericType select i).ToDictionary((Type i) => i.GetGenericTypeDefinition()); } } }