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); }
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); }