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);
        }
Exemple #2
0
        public void GetConcreteMethods_succeeds_for_generic_method(string methodName, Type[] genericArguments)
        {
            var method = GetMethod(methodName);

            var concreteMethods = GenericTypeResolver.GetConcreteMethods(method)
                                  .ToArray( );

            Assert.NotNull(concreteMethods);
            if (genericArguments == null)
            {
                Assert.Empty(concreteMethods);
            }
            else
            {
                Assert.NotEmpty(concreteMethods);
                Assert.Equal(1, concreteMethods.Length);

                var constructedMethod = method.MakeGenericMethod(genericArguments);
                Assert.Equal(constructedMethod, concreteMethods[0]);

                foreach (var parameter in constructedMethod.GetParameters( ))
                {
                    var instances = TypeCreator.GetCreators(parameter.ParameterType);
                    Assert.Equal(1, instances.Count);
                }
            }
        }
        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);
        }
Exemple #5
0
        public void GetConcreteMethods_succeeds_for_concrete_method( )
        {
            var method = GetMethod("ConcreteMethod");

            var concreteMethods = GenericTypeResolver.GetConcreteMethods(method);

            Assert.Equal(method, Assert.Single(concreteMethods));
        }
Exemple #6
0
        public void GetConcreteTypes_returns_argument_for_concrete_type( )
        {
            Type concreteType = typeof(int);

            var types = GenericTypeResolver.GetConcreteTypes(concreteType);

            Assert.Equal(concreteType, Assert.Single(types));
        }
Exemple #7
0
        public void GetConcreteTypes_returns_no_types_for_unconstrained_generic_type( )
        {
            Type genercType = typeof(UnconstrainedGenericType <>);

            var types = GenericTypeResolver.GetConcreteTypes(genercType);

            Assert.Empty(types);
        }
        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);
        }
        /// <summary>
        /// Returns bindings for all assigned generic arguments in the specified list of bindings.
        /// </summary>
        public static void GetAssignedGenericArguments(BindingCollection bindings, Type concreteType, Type genericType)
        {
            Debug.Assert(bindings != null);
            Debug.Assert(concreteType != null);
            Debug.Assert(genericType != null);
            Debug.Assert(concreteType.Is(genericType));

            IEnumerable <Tuple <Type, Type> > concreteTypes = GetConcreteTypes(concreteType, genericType);

            bindings.Expand(concreteTypes, (currentBindings, tuple) => {
                Type type                  = tuple.Item1;
                Type generic               = tuple.Item2;
                Type[] assignedArguments   = type.GetGenericArguments( );
                Type[] unassignedArguments = generic.GetGenericArguments( );
                Debug.Assert(assignedArguments.Length == unassignedArguments.Length);

                for (int i = 0; currentBindings.Count > 0 && i < unassignedArguments.Length; ++i)
                {
                    Type unassignedArgument = unassignedArguments[i];
                    Type assignedArgument   = assignedArguments[i];

                    if (assignedArgument.IsGenericParameter)
                    {
                        continue;
                    }

                    if (!unassignedArgument.IsGenericParameter)
                    {
                        if (unassignedArgument.ContainsGenericParameters)
                        {
                            GenericTypeResolver.GetAssignedGenericArguments(currentBindings, assignedArgument, unassignedArgument);
                        }
                        continue;
                    }

                    if (!assignedArgument.Is(unassignedArgument))
                    {
                        currentBindings.Clear( );
                        break;
                    }

                    currentBindings.Reduce(b => {
                        Binding existingBinding = Binding.ForArgument(b, unassignedArgument);
                        return(existingBinding == null
                             ? b.Add(new Binding(unassignedArgument, assignedArgument))
                             : (existingBinding.Type == assignedArgument ? b : null));
                    });
                }

                if (genericType.IsGenericParameter)
                {
                    currentBindings.Reduce(b => b.Add(new Binding(genericType, 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);
        }
Exemple #12
0
        public void GetConcreteTypes_returns_one_type_for_bound_generic_type( )
        {
            Type genercType            = typeof(UnconstrainedGenericType <>);
            Type genercArgument        = genercType.GetGenericArguments( )[0];
            var  genercArgumentBinding = new Binding(genercArgument, typeof(int));
            var  bindings     = Binding.EmptyBindings.Add(genercArgumentBinding);
            var  concreteType = genercType.MakeGenericType(genercArgumentBinding.Type);

            var types = GenericTypeResolver.GetConcreteTypes(genercType, bindings);

            Assert.Equal(concreteType, Assert.Single(types));
        }
        private static IEnumerable <IInstanceCreator> GetMethodCreators(Type targetType, MethodBase method)
        {
            Debug.Assert(targetType != null);
            Debug.Assert(method != null);
            Debug.Assert(method.IsGenericMethod || !targetType.ContainsGenericParameters);

            // Ignore recursive parameters.
            var parameters = method.GetParameters( );

            if (parameters.Any(p => p.ParameterType.Is(targetType) || p.ParameterType.Is(method.DeclaringType)))
            {
                yield break;
            }

            // Retrieve creators for each parameter.
            var availableArguments = parameters.Select((p) => TypeCreator.GetInstanceCreators(p.ParameterType).AsEnumerable( ));

            // Call constructor with all argument permutations.
            foreach (var arguments in Permuter.Permute(availableArguments))
            {
                // If method is concrete, use it.
                if (!method.IsGenericMethod)
                {
                    yield return(WeakInstanceCreator.ForMethod(targetType, method, arguments));
                }
                // Otherwise, try to resolve generic arguments on method.
                else if (method is MethodInfo)
                {
                    var methodInfo = (MethodInfo)method;
                    var bindings   = new BindingCollection(Binding.EmptyBindings);
                    for (int i = 0; i < parameters.Length; ++i)
                    {
                        ParameterInfo    parameter = parameters[i];
                        IInstanceCreator argument  = arguments[i];
                        if (parameter.ParameterType.ContainsGenericParameters)
                        {
                            GenericTypeResolver.GetAssignedGenericArguments(bindings, argument.InstanceType, parameter.ParameterType);
                        }
                    }

                    foreach (LinkList <Binding> b in bindings)
                    {
                        var concreteMethod = GenericTypeResolver.MakeConcreteMethod(methodInfo, b);
                        if (concreteMethod != null)
                        {
                            targetType = concreteMethod.ReturnType;
                            yield return(WeakInstanceCreator.ForMethod(targetType, concreteMethod, arguments));
                        }
                    }
                }
            }
        }
        public void GetCreators_returns_expected_instances_for_generic_method_argument_types(MethodInfo genericMethod)
        {
            var concreteMethods = GenericTypeResolver.GetConcreteMethods(genericMethod);

            foreach (var method in concreteMethods)
            {
                Type genericType = method.GetParameters( ).Single( ).ParameterType;

                var creators = TypeCreator.GetCreators(genericType);

                TestCreators(genericType, new[] { genericType }, creators);
            }
        }
        private static IEnumerable <IInstanceCreator> GetConstructorCreators(Type targetType, Type availableType)
        {
            Debug.Assert(targetType != null);
            Debug.Assert(availableType != null);
            Debug.Assert(!availableType.IsAbstract);

            if (targetType.ContainsGenericParameters)
            {
                Type definition = targetType.IsGenericParameter ? targetType : targetType.GetGenericTypeDefinition( );
                var  bindings   = new BindingCollection(Binding.EmptyBindings);
                GenericTypeResolver.GetAssignedGenericArguments(bindings, availableType, definition);

                foreach (var binding in bindings)
                {
                    Type resolvedType =
                        definition.IsGenericParameter
                            ? Binding.ForArgument(binding, definition).Type
                            : GenericTypeResolver.MakeConcreteType(definition, binding);

                    targetType = resolvedType;
                    break;
                }
            }

            var creators = new List <IInstanceCreator>( );

            // If type is an enumeration, get creator for enum values.
            if (availableType.IsEnum || availableType == typeof(bool))
            {
                creators.AddRange(WeakInstanceCreator.ForEnum(availableType));
            }
            // Otherwise, get creator for any default constructor.
            else if (Constraint.HasDefaultConstructor(availableType))
            {
                creators.Add(WeakInstanceCreator.ForType(availableType));
            }

            // Get creators for any parameterized constructors.
            var parameterizedConstructors = availableType.GetConstructors( ).Where((c) => c.GetParameters( ).Length > 0).ToArray( );

            if (parameterizedConstructors.Length < 3)
            {
                foreach (var constructor in parameterizedConstructors)
                {
                    creators.AddRange(TypeCreator.GetMethodCreators(targetType, constructor));
                }
            }

            return(creators);
        }
Exemple #16
0
        public void GetConcreteMethods_succeeds_for_generic_class_method( )
        {
            string methodName = "GenericMethod";
            Type   type       = typeof(GenericMethodClass <>);
            var    method     = type.GetMethod(methodName);

            Assert.NotNull(method);

            var concreteMethods = GenericTypeResolver.GetConcreteMethods(method);

            var constructedType   = type.MakeGenericType(typeof(SimpleParameter));
            var constructedMethod = type.GetMethod(methodName);

            Assert.Equal(constructedMethod, Assert.Single(concreteMethods));
        }
        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);
        }
Exemple #19
0
        public void GetConcreteMethods_succeeds_for_generic_method_with_multiple_resolutions( )
        {
            const string methodName = "GenericMethod_MultipleFactoryResolutions";
            var          method     = GetMethod(methodName);

            var concreteMethods = GenericTypeResolver.GetConcreteMethods(method)
                                  .ToArray( );

            Assert.Equal(2, concreteMethods.Length);

            foreach (var concreteMethod in concreteMethods)
            {
                var parameter = concreteMethod.GetParameters( ).Single( );
                var instances = TypeCreator.GetCreators(parameter.ParameterType);
                Assert.Equal(1, instances.Count);
            }
        }
Exemple #20
0
        public void GetConcreteMethods_succeeds_for_generic_method_with_multiple_generic_resolutions(MethodInfo method)
        {
            Type[] resolutionArguments = new[] { typeof(int), typeof(double) };

            var concreteMethods = GenericTypeResolver.GetConcreteMethods(method)
                                  .ToArray( );

            Assert.NotNull(concreteMethods);
            Assert.NotEmpty(concreteMethods);
            Assert.Equal(2, concreteMethods.Length);

            foreach (var m in concreteMethods)
            {
                Type[] genericArguments = m.GetGenericArguments( );
                Assert.NotEmpty(genericArguments);
                Assert.Contains(genericArguments[0], resolutionArguments);
            }
        }
        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);
        }
Exemple #22
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);
            }
        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);
        }
            public static IInstanceCreator ForInstanceCreator(Type targetType, IInstanceCreator creator)
            {
                Debug.Assert(creator != null);
                Debug.Assert(targetType != null);
                Debug.Assert(targetType.IsGenericType && targetType.GetGenericTypeDefinition( ) == typeof(IInstanceCreator <>));

                IInstanceCreator finalCreator      = creator;
                Type             creatorType       = creator.GetType( );
                Type             targetCreatedType = targetType.GetGenericArguments( )[0];

                // Ensure target type is closed.
                Type finalTargetType = targetType;

                if (finalTargetType.ContainsGenericParameters)
                {
                    targetCreatedType = GenericTypeResolver.GetCorrespondingBaseTypes(finalCreator.InstanceType, targetCreatedType).Single( );
                    finalTargetType   = typeof(IInstanceCreator <>).MakeGenericType(targetCreatedType);
                }

                // If the creator does not have the same type as the target, wrap the creator to return instances of the target base type.
                if (!creatorType.Is(finalTargetType))
                {
                    Type actualCreatedType = creatorType.GetInterfaces( )
                                             .Single(i => i.IsGenericType && i.GetGenericTypeDefinition( ) == typeof(IInstanceCreator <>))
                                             .GetGenericArguments( )[0];

                    Type wrapperType = typeof(InstanceCreatorWrapper <,>).MakeGenericType(targetCreatedType, actualCreatedType);
                    finalCreator = (IInstanceCreator)Activator.CreateInstance(wrapperType, creator);
                }

                // Get IInstanceCreator to return the given creator instance.
                Type funcType       = typeof(Func <>).MakeGenericType(finalTargetType);
                var  lambda         = Expression.Lambda(funcType, Expression.Constant(finalCreator, finalTargetType));
                var  nestingCreator = WeakInstanceCreator.ForDelegate(lambda.Compile( ));

                return(nestingCreator);
            }
        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);
        }
Exemple #27
0
        public void GetConcreteTypes_returns_expected_types_for_generic_type(Type genericType, Type[] expectedConcreteTypes)
        {
            var concreteTypes = GenericTypeResolver.GetConcreteTypes(genericType);

            TestConcreteTypes(genericType, expectedConcreteTypes, concreteTypes);
        }
        public static Type MakeConcreteType(Type genericType, LinkList <Binding> bindings)
        {
            var openArguments = GenericTypeResolver.GetOpenGenericArguments(genericType);

            return(GenericTypeResolver.MakeConcreteType(genericType, openArguments, bindings));
        }
 public static ICollection <MethodInfo> GetConcreteMethods(MethodInfo genericMethod)
 {
     return(GenericTypeResolver.GetConcreteMethods(genericMethod, Binding.EmptyBindings));
 }
        public static MethodInfo MakeConcreteMethod(MethodInfo method, LinkList <Binding> bindings)
        {
            var openArguments = GenericTypeResolver.GetOpenGenericArguments(method.GetGenericArguments( ));

            return(GenericTypeResolver.MakeConcreteMethod(method, openArguments, bindings));
        }