internal GenericTypeBuilder(Type closedGenericBaseType, Type openGenericImplementation) { this.closedGenericBaseType = closedGenericBaseType; this.openGenericImplementation = openGenericImplementation; if (openGenericImplementation.Info().IsGenericType && !openGenericImplementation.Info().IsGenericTypeDefinition) { this.openGenericImplementation = openGenericImplementation.GetGenericTypeDefinition(); this.partialOpenGenericImplementation = openGenericImplementation; this.isPartialOpenGenericImplementation = true; } }
// This method takes generic type and returns a 'partially' generic type definition of that same type, // where all generic arguments up to the given nesting level. This allows us to group generic types // by their partial generic type definition, which allows a much nicer user experience. internal static Type MakeTypePartiallyGenericUpToLevel(Type type, int nestingLevel) { if (nestingLevel > 100) { // Stack overflow prevention throw new ArgumentException("nesting level bigger than 100 too high. Type: " + type.ToFriendlyName(), nameof(nestingLevel)); } // example given type: IEnumerable<IQueryProcessor<MyQuery<Alpha>, int[]>> // nestingLevel 4 returns: IEnumerable<IQueryHandler<MyQuery<Alpha>, int[]> // nestingLevel 3 returns: IEnumerable<IQueryHandler<MyQuery<Alpha>, int[]> // nestingLevel 2 returns: IEnumerable<IQueryHandler<MyQuery<T>, int[]> // nestingLevel 1 returns: IEnumerable<IQueryHandler<TQuery, TResult>> // nestingLevel 0 returns: IEnumerable<T> if (!type.Info().IsGenericType) { return type; } if (nestingLevel == 0) { return type.GetGenericTypeDefinition(); } return MakeTypePartiallyGeneric(type, nestingLevel); }
internal static PropertyInfo[] GetCandidateInjectionPropertiesFor(Type implementationType) { var all = BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public; return implementationType.Info().GetProperties(all); }
private ContainerControlledItem[] GetClosedContainerControlledItemsFor(Type serviceType) { var items = this.GetItemsFor(serviceType); return serviceType.Info().IsGenericType ? Helpers.GetClosedGenericImplementationsFor(serviceType, items) : items.ToArray(); }
private InstanceProducer[] GetAssignableProducers(Type closedServiceType) { var producers = from registrationGroup in this.RegistrationGroups where closedServiceType.Info().IsAssignableFrom(registrationGroup.ServiceType) select registrationGroup.UncontrolledProducer; return producers.ToArray(); }
public GenericArgumentFinder(Type serviceTypeDefinition, Type serviceTypeToResolve, Type implementationTypeDefinition, Type partialOpenGenericImplementation) { this.serviceTypeDefinitionArguments = serviceTypeDefinition.Info().GetGenericArguments(); this.serviceTypeToResolveArguments = serviceTypeToResolve.Info().GetGenericArguments(); this.implementationTypeDefinitionArguments = implementationTypeDefinition.Info().GetGenericArguments(); this.partialImplementationArguments = (partialOpenGenericImplementation ?? implementationTypeDefinition).Info().GetGenericArguments(); }
private static Type MakeTypePartiallyGeneric(Type type, int nestingLevel) { var arguments = ( from argument in type.Info().GetGenericArguments() select MakeTypePartiallyGenericUpToLevel(argument, nestingLevel - 1)) .ToArray(); try { return type.GetGenericTypeDefinition().MakeGenericType(arguments.ToArray()); } catch (ArgumentException) { // If we come here, MakeGenericType failed because of generic type constraints. // In that case we skip this nesting level and go one level deeper. return MakeTypePartiallyGenericUpToLevel(type, nestingLevel + 1); } }
private static ConstructorInfo GetSinglePublicConstructor(Type implementationType) { var constructors = implementationType.Info().GetConstructors(); if (!constructors.Any()) { throw new ActivationException( StringResources.TypeMustHaveASinglePublicConstructorButItHasNone(implementationType)); } if (constructors.Length > 1) { throw new ActivationException( StringResources.TypeMustHaveASinglePublicConstructorButItHas(implementationType, constructors.Length)); } return constructors[0]; }
internal static string MixingRegistrationsWithControlledAndUncontrolledIsNotSupported(Type serviceType, bool controlled) => string.Format(CultureInfo.InvariantCulture, "You already made a registration for the {0} type using one of the {3} " + "overloads that registers container-{1} collections, while this method registers container-" + "{2} collections. Mixing calls is not supported. Consider merging those calls or make both " + "calls either as controlled or uncontrolled registration.", (serviceType.Info().IsGenericType ? serviceType.GetGenericTypeDefinition() : serviceType).ToFriendlyName(), controlled ? "uncontrolled" : "controlled", controlled ? "controlled" : "uncontrolled", nameof(Container.RegisterCollection));
internal static string SuppliedTypeDoesNotInheritFromOrImplement(Type service, Type implementation) => string.Format(CultureInfo.InvariantCulture, "The supplied type {0} does not {1} {2}.", implementation.ToFriendlyName(), service.Info().IsInterface ? "implement" : "inherit from", service.ToFriendlyName());
internal static string SuppliedElementDoesNotInheritFromOrImplement(Type serviceType, Type elementType, string elementDescription) => string.Format(CultureInfo.InvariantCulture, "The supplied {0} of type {1} does not {2} {3}.", elementDescription, elementType.ToFriendlyName(), serviceType.Info().IsInterface ? "implement" : "inherit from", serviceType.ToFriendlyName());
internal static IRegistrationEntry Create(Type serviceType, Container container) => serviceType.Info().IsGenericType ? (IRegistrationEntry)new GenericRegistrationEntry(container) : (IRegistrationEntry)new NonGenericRegistrationEntry(serviceType, container);
private static IEnumerable<Type> GetNestedTypeArgumentsForTypeArgument(Type argument, IList<Type> processedArguments) { processedArguments.Add(argument); if (argument.IsGenericParameter) { var nestedArguments = from constraint in argument.Info().GetGenericParameterConstraints() from arg in GetNestedTypeArgumentsForTypeArgument(constraint, processedArguments) select arg; return nestedArguments.Concat(new[] { argument }); } if (!argument.Info().IsGenericType) { return Enumerable.Empty<Type>(); } return from genericArgument in argument.GetGenericArguments().Except(processedArguments) from arg in GetNestedTypeArgumentsForTypeArgument(genericArgument, processedArguments) select arg; }
private CandicateServiceType ToCandicateServiceType(Type openCandidateServiceType) { if (openCandidateServiceType.Info().IsGenericType) { return new CandicateServiceType(openCandidateServiceType, this.GetMatchingGenericArgumentsForOpenImplementationBasedOn(openCandidateServiceType)); } return new CandicateServiceType(openCandidateServiceType, Helpers.Array<Type>.Empty); }
private static bool IsPublicInternal(Type type) { return (type.IsNested ? type.Info().IsNestedPublic : type.Info().IsPublic) && (!type.Info().IsGenericType || type.GetGenericArguments().All(IsPublic)); }
private static IEnumerable<Type> GetNestedTypeArgumentsForType(Type type) => ( from argument in type.Info().GetGenericArguments() from nestedArgument in GetNestedTypeArgumentsForTypeArgument(argument, new List<Type>()) select nestedArgument) .Distinct() .ToArray();
private DiagnosticGroup BuildDiagnosticGroup(Type groupType, IEnumerable<DiagnosticResult> results, int level) => groupType.Info().ContainsGenericParameters ? this.BuildGenericGroup(groupType, results, level) : this.BuildNonGenericGroup(groupType, results);
private Type GetDecoratorTypeFromDecoratorFactory(Type requestedServiceType, DecoratorPredicateContext context) { Type decoratorType = this.data.DecoratorTypeFactory(context); if (decoratorType.Info().ContainsGenericParameters) { if (!requestedServiceType.Info().IsGenericType) { throw new ActivationException( StringResources.TheDecoratorReturnedFromTheFactoryShouldNotBeOpenGeneric( requestedServiceType, decoratorType)); } Requires.TypeFactoryReturnedTypeThatDoesNotContainUnresolvableTypeArguments( requestedServiceType, decoratorType); var builder = new GenericTypeBuilder(requestedServiceType, decoratorType); decoratorType = builder.BuildClosedGenericImplementation().ClosedGenericImplementation; // decoratorType == null when type constraints don't match. if (decoratorType != null) { Requires.HasFactoryCreatedDecorator(this.data.Container, requestedServiceType, decoratorType); } } else { Requires.FactoryReturnsATypeThatIsAssignableFromServiceType(requestedServiceType, decoratorType); } return decoratorType; }
private ArgumentMapping[] ConvertToOpenImplementationArgumentMappingsForType( ArgumentMapping mapping, Type type, IList<Type> processedTypes) { var arguments = mapping.Argument.Info().GetGenericArguments(); var concreteTypes = type.Info().GetGenericArguments(); if (concreteTypes.Length != arguments.Length) { // The length of the concrete list and the generic argument list does not match. This normally // means that the generic argument contains a argument that is not generic (so Int32 instead // of T). In that case we can ignore everything, because the type will be unusable. return Helpers.Array<ArgumentMapping>.Empty; } return ( from subMapping in ArgumentMapping.Zip(arguments, concreteTypes) from arg in this.ConvertToOpenImplementationArgumentMappings(subMapping, processedTypes).ToArray() select arg) .ToArray(); }
private void CheckForOverlappingRegistrations(Type serviceType) { var overlappingGroups = this.GetOverlappingGroupsFor(serviceType); if (overlappingGroups.Any()) { if (!serviceType.Info().ContainsGenericParameters && overlappingGroups.Any(group => group.ServiceType == serviceType)) { throw new InvalidOperationException( StringResources.CollectionTypeAlreadyRegistered(serviceType)); } throw new InvalidOperationException( StringResources.MixingCallsToRegisterCollectionIsNotSupported(serviceType)); } }
private object BuildProducerGroup(Type groupType, InstanceProducer[] producersForGroup, int level) { if (producersForGroup.Length == 1) { var producer = producersForGroup[0]; // This flattens the hierarchy when there is just one item in the group. return new DebuggerViewItem( name: Helpers.ToFriendlyName(producer.ServiceType), description: producer.DebuggerDisplay, value: producersForGroup[0]); } if (groupType.Info().ContainsGenericParameters) { return this.BuildGenericGroup(groupType, producersForGroup, level); } else { return BuildNonGenericGroup(groupType, producersForGroup); } }
private IEnumerable<RegistrationGroup> GetOverlappingGroupsFor(Type serviceType) => from registrationGroup in this.RegistrationGroups where !registrationGroup.Appended where registrationGroup.ServiceType == serviceType || serviceType.Info().ContainsGenericParameters || registrationGroup.ServiceType.Info().ContainsGenericParameters select registrationGroup;