private static IEnumerable <IInstanceCreator> GetGenericCreators(Type targetType, Type genericType)
        {
            Debug.Assert(targetType != null);
            Debug.Assert(genericType != null);
            Debug.Assert(genericType.ContainsGenericParameters);

            // Get all bindings for the generic type's arguments that satisfy the inheritance constraint.
            var openArguments = GenericTypeResolver.GetOpenGenericArguments(genericType);

            Assembly[]            referenceAssemblies;
            LinkList <Constraint> inheritanceConstraints =
                targetType.IsGenericParameter
                    ? Constraint.GetConstraints(targetType, out referenceAssemblies)
                    : Constraint.GetInheritanceConstraint(targetType).MakeLinkList( );
            var argumentBindings = new BindingCollection(Binding.EmptyBindings);

            Constraint.SatisfyConstraints(argumentBindings, genericType, inheritanceConstraints);

            // Construct concrete types for each set of argument bindings,
            //  and return the creators for each concrete type.
            var creators =
                from arguments in argumentBindings
                let concreteType = GenericTypeResolver.CreateConcreteType(genericType, openArguments, arguments)
                                   where concreteType != null
                                   from creator in TypeCreator.GetInstanceCreators(targetType, concreteType)
                                   select creator;

            return(creators);
        }
        public void GetOpenGenericArguments_returns_expected_number_of_arguments_for_type(Type type, int expectedCount)
        {
            var arguments = GenericTypeResolver.GetOpenGenericArguments(type);

            Assert.NotNull(arguments);
            Assert.Equal(expectedCount, arguments.Count);
        }
        public void CreateConcreteType_returns_null_for_generic_type_with_partial_bindings( )
        {
            Type type          = typeof(IDictionary <,>);
            var  openArguments = GenericTypeResolver.GetOpenGenericArguments(type);
            var  bindings      = Binding.EmptyBindings.Add(new Binding(openArguments.Value, typeof(int)));

            var concreteType = GenericTypeResolver.CreateConcreteType(type, openArguments, bindings);

            Assert.Null(concreteType);
        }
        public void CreateConcreteType_returns_null_for_generic_type_with_no_bindings( )
        {
            Type type          = typeof(Nullable <>);
            var  openArguments = GenericTypeResolver.GetOpenGenericArguments(type);
            var  bindings      = Binding.EmptyBindings;

            var concreteType = GenericTypeResolver.CreateConcreteType(type, openArguments, bindings);

            Assert.Null(concreteType);
        }
        public void CreateConcreteType_succeeds_for_concrete_type( )
        {
            Type type          = typeof(int);
            var  openArguments = GenericTypeResolver.GetOpenGenericArguments(type);
            var  bindings      = Binding.EmptyBindings;

            var concreteType = GenericTypeResolver.CreateConcreteType(type, openArguments, bindings);

            Assert.NotNull(concreteType);
            Assert.Equal(type, concreteType);
        }
        public void CreateConcreteType_succeeds_for_generic_type_with_duplicate_bindings( )
        {
            Type genericType   = typeof(Nullable <>);
            var  openArguments = GenericTypeResolver.GetOpenGenericArguments(genericType);
            var  bindings      = GetBindingList(new[] { new Binding(openArguments.Value, typeof(int)), new Binding(openArguments.Value, typeof(int)) });

            var concreteType = GenericTypeResolver.CreateConcreteType(genericType, openArguments, bindings);

            Assert.NotNull(concreteType);
            Assert.Equal(genericType, concreteType.GetGenericTypeDefinition( ));

            var constructedType = genericType.MakeGenericType(typeof(int));

            Assert.Equal(constructedType, concreteType);
        }
        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);
        }
        public void CreateConcreteType_succeeds_for_generic_type_with_full_bindings(Type genericType)
        {
            var openArguments = GenericTypeResolver.GetOpenGenericArguments(genericType);
            var bindings      = GetBindingList(openArguments.Select((a, i) => new Binding(a, typeof(int))));

            var concreteType = GenericTypeResolver.CreateConcreteType(genericType, openArguments, bindings);

            Assert.NotNull(concreteType);
            Assert.Equal(genericType, concreteType.GetGenericTypeDefinition( ));

            Type[] typeArguments = new Type[bindings.Count];
            for (int i = 0; i < typeArguments.Length; ++i)
            {
                typeArguments[i] = typeof(int);
            }
            var constructedType = genericType.MakeGenericType(typeArguments);

            Assert.Equal(constructedType, 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);
        }
        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));
        }
 /// <summary>
 /// Returns all unassigned generic arguments on the <paramref name="genericType"/>.
 /// </summary>
 public static LinkList <Type> GetOpenGenericArguments(Type genericType)
 {
     return(GenericTypeResolver.GetOpenGenericArguments(genericType.GetGenericArguments( )));
 }