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);
        }
Beispiel #2
0
        public void Transform_GivenItemTransformer_RemovesDuplicateResults( )
        {
            var initial    = new[] { List(typeof(double)), List(typeof(double)) };
            var expected   = new[] { initial[1].Value };
            var collection = new BindingCollection(initial);

            var results = collection.Transform((b) => b.Value);
            var actual  = results.ToArray( );

            Assert.Equal(actual, expected);
        }
        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);
        }