private static MethodInfo MakeConcreteMethod(MethodInfo method, LinkList <Type> openArguments, LinkList <Binding> bindings)
        {
            Debug.Assert(method != null);
            Debug.Assert(openArguments != null);
            Debug.Assert(bindings != null);

            // If the method is not generic, return it immediately.
            if (!method.IsGenericMethodDefinition)
            {
                Debug.Assert(openArguments.IsEmpty);
                return(method);
            }

            // Otherwise, retrieve bindings for open arguments and construct the method.
            var boundArguments = GenericTypeResolver.BindConcreteArguments(openArguments, bindings);

            var concreteMethod = (boundArguments.Length == openArguments.Count
                ? method.MakeGenericMethod(boundArguments)
                : null);

            return(concreteMethod);
        }
        private static Type MakeConcreteType(Type genericType, LinkList <Type> openArguments, LinkList <Binding> bindings)
        {
            Debug.Assert(genericType != null);
            Debug.Assert(openArguments != null);
            Debug.Assert(bindings != null);

            // If the type is concrete, return it immediately.
            if (!genericType.ContainsGenericParameters)
            {
                Debug.Assert(openArguments.IsEmpty);
                return(genericType);
            }

            // Otherwise, retrieve bindings for open arguments and construct the type.
            var boundArguments = GenericTypeResolver.BindConcreteArguments(openArguments, bindings);

            Debug.Assert(boundArguments.Length <= openArguments.Count);
            var concreteType = (boundArguments.Length == openArguments.Count
                ? genericType.MakeGenericType(boundArguments)
                : null);

            return(concreteType);
        }
        private static BindingCollection GetConcreteTypeBindings(Type type, LinkList <Binding> bindings, out LinkList <Type> openArguments)
        {
            Debug.Assert(type != null);
            Debug.Assert(bindings != null);


            // Avoid recursive searches for generic type.
            if (type.ContainsGenericParameters)
            {
                if (Binding.ContainsType(bindings, type))
                {
                    openArguments = LinkList <Type> .Empty;
                    return(new BindingCollection( ));
                }
                bindings = bindings.Add(new Binding(null, type));
            }

            // Bind all unassigned generic argument on the generic type.
            openArguments = GenericTypeResolver.GetOpenGenericArguments(type);
            var collection = new BindingCollection(bindings);

            GenericTypeResolver.BindGenericArguments(collection, openArguments);
            return(collection);
        }
Beispiel #4
0
            protected override IEnumerable <LinkList <Binding> > SatisfyCore(Type availableType, LinkList <Binding> bindings)
            {
                var newBindings    = new List <LinkList <Binding> >( );
                var currentBindngs = new BindingCollection(bindings);

                // Check if the available type derives from the base type.
                if (availableType.Is(this.requiredBaseType_))
                {
                    // Add any generic arguments assigned by the base type.
                    if (this.requiredBaseType_.IsGenericType && !this.requiredBaseType_.ContainsGenericParameters)
                    {
                        IEnumerable <Type> correspondingTypes = GenericTypeResolver.GetCorrespondingBaseTypes(availableType, this.requiredBaseType_);
                        foreach (Type correspondingType in correspondingTypes)
                        {
                            if (correspondingType.ContainsGenericParameters)
                            {
                                GenericTypeResolver.GetAssignedGenericArguments(currentBindngs, this.requiredBaseType_, correspondingType);
                            }
                        }
                    }

                    // Check all concrete version of the available type.
                    foreach (LinkList <Binding> b in currentBindngs)
                    {
                        var concreteTypes = GenericTypeResolver.GetConcreteTypes(availableType, b);
                        foreach (Type concreteAvailableType in concreteTypes)
                        {
                            // Add any newly assigned bindings from concrete and base types.
                            var assignedBindings = new BindingCollection(b);
                            GenericTypeResolver.GetAssignedGenericArguments(assignedBindings, concreteAvailableType, availableType);
                            if (this.requiredBaseType_.ContainsGenericParameters)
                            {
                                GenericTypeResolver.GetAssignedGenericArguments(assignedBindings, concreteAvailableType, this.requiredBaseType_);
                            }

                            newBindings.AddRange(assignedBindings);
                        }
                    }
                }

                return(newBindings);
            }
 protected override IEnumerable <LinkList <Binding> > SatisfyCore(Type availableType, LinkList <Binding> bindings)
 {
     if (this.condition_(availableType))
     {
         return(bindings.MakeEnumerable( ));
     }
     return(Constraint.NoBindings);
 }
        public static MethodInfo MakeConcreteMethod(MethodInfo method, LinkList <Binding> bindings)
        {
            var openArguments = GenericTypeResolver.GetOpenGenericArguments(method.GetGenericArguments( ));

            return(GenericTypeResolver.MakeConcreteMethod(method, openArguments, bindings));
        }
        public static Type MakeConcreteType(Type genericType, LinkList <Binding> bindings)
        {
            var openArguments = GenericTypeResolver.GetOpenGenericArguments(genericType);

            return(GenericTypeResolver.MakeConcreteType(genericType, openArguments, bindings));
        }
 public static ReadOnlyCollection <Type> GetConcreteTypes(Type genericType, LinkList <Binding> bindings)
 {
     return(GenericTypeResolver.GetConcreteTypesCore(genericType, bindings));
 }
 /// <summary>
 /// Creates an instance of the <paramref name="genericType"/> by assigning each of the <paramref name="openArguments"/>
 ///  to the concrete type specified by the <paramref name="bindings"/>.
 /// </summary>
 public static Type CreateConcreteType(Type genericType, LinkList <Type> openArguments, LinkList <Binding> bindings)
 {
     return(GenericTypeResolver.MakeConcreteType(genericType, openArguments, bindings));
 }
        private static IEnumerable <T[]> Permute <T>(LinkList <LinkList <T> > availableItems, LinkList <T> currentPermutation)
        {
            // If there are no remaining available items, return current permutation.
            if (availableItems.IsEmpty)
            {
                return(currentPermutation.ToArray( ).MakeEnumerable( ));
            }

            // Otherwise, loop through all of the current available items,
            //  returning permutations of the remaining items.
            var currentAvailableItems   = availableItems.Value;
            var remainingAvailableItems = availableItems.Tail;

            Debug.Assert(currentAvailableItems != null);
            return
                (from item in currentAvailableItems
                 let nextPermutation = currentPermutation.Add(item)
                                       from permutation in Permuter.Permute(remainingAvailableItems, nextPermutation)
                                       select permutation);
        }
        /// <summary>
        /// Adds the specified bindings to the collection.
        /// </summary>
        public void Add(LinkList <Binding> bindings)
        {
            Debug.Assert(bindings != null);

            this.bindings_.Add(bindings);
        }
        private static ICollection <MethodInfo> GetConcreteMethods(MethodInfo method, LinkList <Binding> bindings)
        {
            Debug.Assert(method != null);
            Debug.Assert(bindings != null);


            // Try to resolve generic arguments on method.
            var openArguments    = GenericTypeResolver.GetOpenGenericArguments(method.GetGenericArguments( ));
            var concreteBindings = new BindingCollection(bindings);

            GenericTypeResolver.BindGenericArguments(concreteBindings, openArguments);

            var concreteMethods = concreteBindings.Transform((b) => MakeConcreteMethod(method, openArguments, b));


            // If generic arguments cannot be resolved statically, try to bind method arguments by searching for creatable parameter types.
            if (concreteMethods.Count == 0)
            {
                var genericParameterTypes = method.GetParameters( )
                                            .Select(p => p.ParameterType)
                                            .Where(t => t.IsGenericType)
                                            .ToArray( );
                Debug.Assert(genericParameterTypes.All(t => !t.IsGenericParameter));

                var creatableParameterTypes = genericParameterTypes
                                              .Select(t => TypeCreator.GetCreators(t)
                                                      .Select(c => c.InstanceType)
                                                      .Distinct( )
                                                      );

                var parameterBindings = new BindingCollection(bindings);
                parameterBindings.Expand(Permuter.Permute(creatableParameterTypes), (b, permutation) => {
                    for (int i = 0; i < permutation.Length; ++i)
                    {
                        Type permutationType      = permutation[i];
                        Type genericParameterType = genericParameterTypes[i];
                        GenericTypeResolver.GetAssignedGenericArguments(b, permutationType, genericParameterType);
                    }
                });

                concreteMethods = parameterBindings.Transform((b) => MakeConcreteMethod(method, openArguments, b));
            }


            return(concreteMethods);
        }
        private static ReadOnlyCollection <Type> GetConcreteTypesCore(Type genericType, LinkList <Binding> bindings)
        {
            Debug.Assert(genericType != null);
            Debug.Assert(bindings != null);

            bool cached  = concreteTypeCache_.ContainsKey(genericType);
            bool unbound = genericType.GetGenericArguments( )
                           .All((a) => !Binding.ContainsArgument(bindings, a));

            // If the type has already been evaluated and there are no interfering bindings, return cached value.
            if (cached && unbound)
            {
                return(concreteTypeCache_[genericType]);
            }


            // Otherwise, get a concrete type for each set of bindings.
            LinkList <Type>   openArguments;
            BindingCollection concreteTypeBindngs = GenericTypeResolver.GetConcreteTypeBindings(genericType, bindings, out openArguments);
            var concreteTypes = concreteTypeBindngs
                                .Transform((argumentBindings) => MakeConcreteType(genericType, openArguments, argumentBindings))
                                .ToReadOnlyCollection( );

            // If there are no interfering bindings, cache the concrete types.
            if (!cached && unbound)
            {
                concreteTypeCache_.TryAdd(genericType, concreteTypes);
                concreteTypes = concreteTypeCache_[genericType];
            }

            return(concreteTypes);
        }
 /// <summary>
 /// Implements the logic behind <see cref="Constraint.Satisfy"/>.
 /// </summary>
 protected abstract IEnumerable <LinkList <Binding> > SatisfyCore(Type availableType, LinkList <Binding> bindings);