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