private CachingResult LoadEnumerable(ILGenerator ilGenerator, IEnumerable enumerable) { Assumes.NotNull(ilGenerator); Assumes.NotNull(enumerable); CachingResult result = CachingResult.SucceededResult; // We load enumerable as an array - this is the most compact and efficient way of representing it Type elementType = null; Type closedType = null; if (GenerationServices.TryGetGenericInterfaceType(enumerable.GetType(), GenerationServices.IEnumerableTypeofT, out closedType)) { elementType = closedType.GetGenericArguments()[0]; } else { elementType = typeof(object); } elementType = GenerationServices.NormalizeCollectionElementType(elementType); // // elem[] array = new elem[<enumerable.Count()>] // GenerationServices.LoadInt(ilGenerator, enumerable.Cast<object>().Count()); ilGenerator.Emit(OpCodes.Newarr, elementType); // at this point we have the array on the stack int index = 0; foreach (object value in enumerable) { // //array[<index>] = value; // // load the array on teh stack again ilGenerator.Emit(OpCodes.Dup); GenerationServices.LoadInt(ilGenerator, index); result = result.MergeResult(this.LoadValue(ilGenerator, value)); if (GenerationServices.IsBoxingRequiredForValue(value) && !elementType.IsValueType) { ilGenerator.Emit(OpCodes.Box, value.GetType()); } ilGenerator.Emit(OpCodes.Stelem, elementType); index++; // at this point we have the array on teh stack again } // the array is already on the stack - just exit return result; }
private static Type NormalizeCollectionElementType(Type type) { if (GenerationServices.IEnumerableType.IsAssignableFrom(type) && type != GenerationServices.StringType) { // the element is IEnumerable. we need to normalize it to be literally IEnumerable Type closedType = null; if (GenerationServices.TryGetGenericInterfaceType(type, GenerationServices.IEnumerableTypeofT, out closedType)) { return GenerationServices.IEnumerableTypeofT.MakeGenericType(GenerationServices.NormalizeCollectionElementType(closedType.GetGenericArguments()[0])); } else { return typeof(IEnumerable<object>); } } else { return type; } }