/// <summary> /// Returns all permutations in the collections of available items. /// </summary> public static T[][] Permute <T>(IEnumerable <IEnumerable <T> > availableItems) { Debug.Assert(availableItems != null); var listedItems = availableItems .Select((itemCollection) => itemCollection.ToLinkList( )) .ToLinkList( ); return(Permuter.Permute(listedItems, LinkList <T> .Empty).ToArray( )); }
public void Permute_returns_expected_permutation(int[][] items, int[][] expectedPermutations) { var permutations = Permuter.Permute(items); Assert.NotNull(permutations); Assert.Equal(expectedPermutations.Length, permutations.Length); foreach (var permutation in permutations) { Assert.Contains(permutation, expectedPermutations, ArrayComparer <int> .Instance); } }
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)); } } } } }
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 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); }