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

DefaultGenericHandler

using Castle.Core; using Castle.Core.Internal; using Castle.DynamicProxy; using Castle.MicroKernel.ComponentActivator; using Castle.MicroKernel.Context; using Castle.MicroKernel.ModelBuilder; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; namespace Castle.MicroKernel.Handlers { [Serializable] 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(); for (int i = 0; i < array.Length; i++) { (array[i] as IDisposable)?.Dispose(); } } public override bool ReleaseCore(Burden burden) { Type unproxiedType = ProxyUtil.GetUnproxiedType(burden.Instance); return type2SubHandler.GetOrThrow(unproxiedType).Release(burden); } public override bool Supports(Type service) { if (base.Supports(service)) return true; if (type2SubHandler.Contains(service)) return true; if (service.GetTypeInfo().IsGenericType && !service.GetTypeInfo().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.GetTypeInfo().IsGenericType || service.GetTypeInfo().IsGenericTypeDefinition) return false; Type[] serviceArguments = service.GetGenericArguments(); return base.ComponentModel.Services.Any((Type s) => SupportsAssignable(service, s, serviceArguments)); } protected virtual Type[] AdaptServices(Type closedImplementationType, Type requestedType) { Type[] array = base.ComponentModel.Services.ToArray(); if (array.Length == 1 && requestedType.GetTypeInfo().IsGenericType && array[0] == requestedType.GetGenericTypeDefinition()) return new Type[1] { requestedType }; List<Type> list = new List<Type>(array.Length); int num = AdaptClassServices(closedImplementationType, list, array); if (num == array.Length - 1 && list.Count > 0) return list.ToArray(); AdaptInterfaceServices(closedImplementationType, list, array, num); if (list.Count == 0) return new Type[1] { requestedType }; return list.ToArray(); } protected virtual IHandler BuildSubHandler(Type closedImplementationType, Type requestedType) { ComponentModel componentModel = base.Kernel.ComponentModelBuilder.BuildModel(base.ComponentModel.ComponentName, AdaptServices(closedImplementationType, requestedType), closedImplementationType, GetExtendedProperties()); CloneParentProperties(componentModel); return base.Kernel.CreateHandler(componentModel); } protected IHandler GetSubHandler(Type genericType, Type requestedType) { bool added = false; IHandler orAdd = type2SubHandler.GetOrAdd(genericType, delegate(Type t) { added = true; return BuildSubHandler(t, requestedType); }); if (added) base.Kernel.RaiseEventsOnHandlerCreated(orAdd); return orAdd; } protected override void InitDependencies() { IDependencyAwareActivator dependencyAwareActivator = base.Kernel.CreateComponentActivator(base.ComponentModel) as IDependencyAwareActivator; if (dependencyAwareActivator != null && dependencyAwareActivator.CanProvideRequiredDependencies(base.ComponentModel)) { foreach (DependencyModel dependency in base.ComponentModel.Dependencies) { dependency.Init(base.ComponentModel.ParametersInternal); } } else base.InitDependencies(); } protected override object Resolve(CreationContext context, bool instanceRequired) { Type closedImplementationType = GetClosedImplementationType(context, instanceRequired); if (closedImplementationType == (Type)null) return null; IHandler subHandler = GetSubHandler(closedImplementationType, context.RequestedType); 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.GetTypeInfo().IsGenericTypeDefinition || modelService.GetGenericArguments().Length != serviceArguments.Length) return false; Type type = modelService.TryMakeGenericType(serviceArguments); if (type == (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) { Arguments customDependencies = newModel.CustomDependencies; foreach (KeyValuePair<object, object> customDependency in base.ComponentModel.CustomDependencies) { customDependencies.Add(customDependency.Key, customDependency.Value); } } ICollection<IMetaComponentModelDescriptor> metaDescriptors = base.ComponentModel.GetMetaDescriptors(false); if (metaDescriptors != null) { foreach (IMetaComponentModelDescriptor item in metaDescriptors) { item.ConfigureComponentModel(base.Kernel, newModel); } } } public IHandler ConvertToClosedGenericHandler(Type service, CreationContext openGenericContext) { Type closedImplementationType = GetClosedImplementationType(openGenericContext, false); return GetSubHandler(closedImplementationType, service); } private Type GetClosedImplementationType(CreationContext context, bool instanceRequired) { if (!(base.ComponentModel.Implementation == typeof(LateBoundComponent))) { 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 consult 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 consult 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 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; } } return context.RequestedType; } private Arguments GetExtendedProperties() { Arguments arguments = base.ComponentModel.ExtendedProperties; if (arguments != null && arguments.Count > 0) arguments = new Arguments(arguments); return arguments; } 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].GetTypeInfo().IsClass; i++) { Type type = openServices[i]; if (type.GetTypeInfo().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.GetTypeInfo().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 (type != typeof(object)) { if (type.GetTypeInfo().IsGenericType) genericDefinitionToClass.Add(type.GetGenericTypeDefinition(), type); type = type.GetTypeInfo().BaseType; } } } private static void EnsureInterfaceMappingInitialized(Type closedImplementationType, ref IDictionary<Type, Type> genericDefinitionToInterface) { if (genericDefinitionToInterface == null) genericDefinitionToInterface = (from i in closedImplementationType.GetInterfaces() where i.GetTypeInfo().IsGenericType select i).ToDictionary((Type i) => i.GetGenericTypeDefinition()); } } }