예제 #1
0
        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;
        }
예제 #2
0
 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;
     }
 }
예제 #3
0
        private CachingResult LoadGenericDictionary<TKey, TValue>(ILGenerator ilGenerator, IDictionary<TKey, TValue> dictionary, bool isStandardDictionary)
        {
            Assumes.NotNull(ilGenerator);
            Assumes.NotNull(dictionary);

            CachingResult result = CachingResult.SucceededResult;
            Type keyType = GenerationServices.NormalizeCollectionElementType(typeof(TKey));
            Type valueType = GenerationServices.NormalizeCollectionElementType(typeof(TValue));

            Type dictionaryType = null;
            MethodInfo dictionaryAddMethod = null;
            ConstructorInfo dictionaryConstructor = null;
            if (isStandardDictionary)
            {
                dictionaryType = GenerationServices.standardDictionaryType;
                dictionaryAddMethod = GenerationServices.standardDictionaryAddMethod;
                dictionaryConstructor = dictionaryType.GetConstructor(new Type[] { Int32Type });
            }
            else
            {
                dictionaryType = GenerationServices.GenericDictionaryType.MakeGenericType(keyType, valueType);
                dictionaryAddMethod = dictionaryType.GetMethod("Add", new Type[] { keyType, valueType });
                dictionaryConstructor = dictionaryType.GetConstructor(new Type[] { Int32Type });
            }

            //
            // Dictionary<TKey, TValue> metadata = new Dictionary<TKey, TValue>(capacity)
            //

            // create and load the dictionary
            GenerationServices.LoadInt(ilGenerator, dictionary.Count);
            ilGenerator.Emit(OpCodes.Newobj, dictionaryConstructor);


            // 
            // Generate a sequence of "Add" statements
            //
            
            foreach (KeyValuePair<TKey, TValue> dictionaryItem in dictionary)
            {
                //
                // metadata.Add(key, value)
                //

                // the dictionary is on top of the stack - load it again
                ilGenerator.Emit(OpCodes.Dup);
               

                // load the key, boxing if necessary
                result = result.MergeResult(this.LoadValue(ilGenerator, dictionaryItem.Key));
                // key = string for standard dictionaries, so no boxing is ever required
                if (!isStandardDictionary && GenerationServices.IsBoxingRequiredForValue(dictionaryItem.Key) && !keyType.IsValueType)
                {
                    ilGenerator.Emit(OpCodes.Box, dictionaryItem.Key.GetType());
                }

                // load the value, boxing if necessary
                result = result.MergeResult(this.LoadValue(ilGenerator, dictionaryItem.Value));
                // key = object for standard dictionaries, so value type is never a struct
                if (GenerationServices.IsBoxingRequiredForValue(dictionaryItem.Value) && (isStandardDictionary || !valueType.IsValueType) )
                {
                    ilGenerator.Emit(OpCodes.Box, dictionaryItem.Value.GetType());
                }

                // Caal the "Add"
                ilGenerator.EmitCall(OpCodes.Call, dictionaryAddMethod, null);

                // At this point the dictionary, key and value have been popped off the stack, and we ended up with the origical state of the dictionary on top of the stack
            }

            // 
            // the dicationary is already loaded on the stack - exit
            //
            return result;

        }