internal ForEachExpression( ParameterExpression variable, Expression enumerable, Expression body, LabelTarget?breakTarget, LabelTarget?continueTarget) { _enumerableTypeDescriptor = EnumerableTypeDescriptor.GetTypeDescriptor(enumerable.Type); if (!_enumerableTypeDescriptor.IsEnumerable) { throw new ArgumentException("The specified argument is not enumerable.", nameof(enumerable)); } Variable = variable; Enumerable = enumerable; Body = body; BreakTarget = breakTarget ?? Expression.Label("break"); ContinueTarget = continueTarget ?? Expression.Label("continue"); }
public static IEnumerable CloneTo(this IEnumerable enumerable, Type typeToBuild) { if (typeToBuild is null) { throw new ArgumentNullException(nameof(typeToBuild)); } var enumerableTypeDescriptor = EnumerableTypeDescriptor.Get(typeToBuild); if (!enumerableTypeDescriptor.IsEnumerable) { throw new ArgumentException(nameof(typeToBuild), $"Type {typeToBuild.Name} is not an IEnumerable type."); } if (enumerable is null) { if (typeToBuild.IsArrayOrArrayClass()) { return(Array.CreateInstance(enumerableTypeDescriptor.ExplicitImplementation.ElementType, 0)); } if (enumerableTypeDescriptor.ParameterlessConstructor is null) { throw new InvalidOperationException($"Cannot create enumerable of type {typeToBuild.Name}. The type does not provide a parameterless constructor."); } return((IEnumerable)enumerableTypeDescriptor.ParameterlessConstructor.Invoke()); } if (typeToBuild.IsArrayOrArrayClass()) { return(enumerable.DynamicToArray(enumerableTypeDescriptor.ExplicitImplementation.ElementType)); } var ctor = enumerableTypeDescriptor.ConstructorsWithEnumerableParameter .Where(x => x.Key.IsInstanceOfType(enumerable)) .Select(x => x.Value) .FirstOrDefault(); if (ctor != null) { return((IEnumerable)ctor.Invoke(enumerable)); } if (enumerableTypeDescriptor.ParameterlessConstructor == null) { throw new InvalidOperationException($"Cannot create enumerable of type {typeToBuild.Name} from data of type {enumerable.GetType().Name}. The type does not provide a proper constructor with a single parameter for data, nor a parameterless constructor."); } var instance = (IEnumerable)enumerableTypeDescriptor.ParameterlessConstructor.Invoke(); if (enumerableTypeDescriptor.ExplicitImplementation.Kind == EnumerableInterfaceKind.Dictionary) { foreach (var item in enumerable) { var entry = GetKeyValuePair(item); var addMethod = enumerableTypeDescriptor.GetApplicableDictionaryMethod(DictionaryMethod.Add, entry); if (addMethod == null) { throw new InvalidOperationException($"Cannot add element of type {item?.GetType()} to dictionary of type {instance.GetType()}. No applicable Add method was found on the type"); } addMethod.MethodInfoEx.Invoke(instance, entry.key, entry.value); } } else { var index = 0; foreach (var item in enumerable) { var applicableMethod = enumerableTypeDescriptor.GetApplicableListMethod(ListMethod.Add, item) ?? enumerableTypeDescriptor.GetApplicableListMethod(ListMethod.Insert, item); if (applicableMethod is null) { throw new InvalidOperationException($"Cannot add element of type {item?.GetType()} to collection of type {instance.GetType()}. No applicable Add or Insert methods were found on the type"); } else { try { if (applicableMethod.Method == ListMethod.Add) { applicableMethod.MethodInfoEx.Invoke(instance, item); } else { applicableMethod.MethodInfoEx.Invoke(instance, index, item); } } catch (Exception e) { throw new InvalidOperationException($"Cannot add element of type {item?.GetType()} to collection of type {instance.GetType()}. No applicable Add or Insert method was found on the type or the applicable method failed (see inner exception).", e); } } index++; } } return(instance); }