示例#1
0
        private ArgumentMapping[] GetTypeConstraintArgumentMappingsRecursive(ArgumentMapping mapping, IList <Type> processedTypes)
        {
            IEnumerable <Type> constraints = Enumerable.Empty <Type>();

            if (mapping.Argument.IsGenericParameter)
            {
                //// If the type itself is a generic parameter such as TKey (and not for instance IBar<TValue>)
                //// We must skip it, since there is no mappings we can extract from it (while IBar<TValue> could).
                constraints =
                    from constraint in mapping.Argument.GetGenericParameterConstraints()
                    where !constraint.IsGenericParameter
                    select constraint;
            }
            else
            {
                // In case we're dealing with partial generic type's (such as Lazy<List<T>>) the argument is
                // not a generic parameter and the argument (List<T> for instance) itself becomes the
                // constraints.
            }

            return((
                       from constraint in constraints
                       let constraintMapping = new ArgumentMapping(constraint, mapping.ConcreteType)
                                               from arg in this.ConvertToOpenImplementationArgumentMappings(constraintMapping, processedTypes).ToArray()
                                               select arg)
                   .ToArray());
        }
示例#2
0
        private IEnumerable <ArgumentMapping> ConvertToOpenImplementationArgumentMappings(
            ArgumentMapping mapping, IList <Type> processedTypes)
        {
            // We are only interested in generic parameters
            if (mapping.Argument.IsGenericArgument() && !processedTypes.Contains(mapping.Argument))
            {
                processedTypes.Add(mapping.Argument);

                if (this.implementationTypeDefinitionArguments.Contains(mapping.Argument))
                {
                    // The argument is one of the type's generic arguments. We can directly return it.
                    yield return(mapping);

                    foreach (var arg in this.GetTypeConstraintArgumentMappingsRecursive(mapping, processedTypes))
                    {
                        yield return(arg);
                    }
                }
                else
                {
                    // The argument is not in the type's list, which means that the real type is (or are)
                    // buried in a generic type (i.e. Nullable<KeyValueType<TKey, TValue>>). This can result
                    // in multiple values.
                    foreach (var arg in this.ConvertToOpenImplementationArgumentMappingsRecursive(mapping, processedTypes))
                    {
                        yield return(arg);
                    }
                }
            }
        }
示例#3
0
        private ArgumentMapping[] ConvertToOpenImplementationArgumentMappingsForType(
            ArgumentMapping mapping, Type type, IList <Type> processedTypes)
        {
            var arguments     = mapping.Argument.GetGenericArguments();
            var concreteTypes = type.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(new ArgumentMapping[0]);
            }

            return((
                       from subMapping in ArgumentMapping.Zip(arguments, concreteTypes)
                       from arg in this.ConvertToOpenImplementationArgumentMappings(subMapping, processedTypes).ToArray()
                       select arg)
                   .ToArray());
        }
示例#4
0
        private ArgumentMapping[] ConvertToOpenImplementationArgumentMappingsRecursive(
            ArgumentMapping mapping, IList <Type> processedTypes)
        {
            // If we're dealing with a generic type argument here (which means we're in the verification
            // phase testing open generic types), we must just return the mapping, because we can't deduce
            // things any further.
            if (mapping.ConcreteType.IsGenericParameter)
            {
                return(new ArgumentMapping[] { mapping });
            }

            var argumentTypeDefinition = mapping.Argument.GetGenericTypeDefinition();

            // Try to get mappings for each type in the type hierarchy that is compatible to the  argument.
            return((
                       from type in mapping.ConcreteType.GetTypeBaseTypesAndInterfacesFor(argumentTypeDefinition)
                       from arg in this.ConvertToOpenImplementationArgumentMappingsForType(mapping, type, processedTypes)
                       select arg)
                   .ToArray());
        }