public static bool TryGetCollectionMetaToken(Type actualType, out CollectionMetaToken token) { if (!IsCollection(actualType)) { token = null; return false; } token = new CollectionMetaToken(actualType); return true; }
private void WriteDictionary(CollectionMetaToken collectionToken, int count, object dictionary) { writer.Write(count); if(collectionToken.IsGeneric) { var enumeratorMethod = typeof(IEnumerable<>).MakeGenericType(typeof(KeyValuePair<,>).MakeGenericType(collectionToken.FormalKeyType, collectionToken.FormalValueType)).GetMethod("GetEnumerator"); var enumerator = enumeratorMethod.Invoke(dictionary, null); var enumeratorType = enumeratorMethod.ReturnType; var moveNext = Helpers.GetMethodInfo<IEnumerator>(x => x.MoveNext()); var currentField = enumeratorType.GetProperty("Current"); var current = currentField.GetGetMethod(); var currentType = current.ReturnType; var key = currentType.GetProperty("Key").GetGetMethod(); var value = currentType.GetProperty("Value").GetGetMethod(); while((bool)moveNext.Invoke(enumerator, null)) { var currentValue = current.Invoke(enumerator, null); var keyValue = key.Invoke(currentValue, null); var valueValue = value.Invoke(currentValue, null); WriteField(collectionToken.FormalKeyType, keyValue); WriteField(collectionToken.FormalValueType, valueValue); } } else { var castDictionary = (IDictionary)dictionary; foreach(DictionaryEntry element in castDictionary) { WriteField(typeof(object), element.Key); WriteField(typeof(object), element.Value); } } }
private bool WriteSpecialObject(object o) { // if the object here is value type, it is in fact boxed // value type - the reference layout is fine, we should // write it using WriteField var type = o.GetType(); if (type.IsValueType) { WriteField(type, o); return(true); } var speciallySerializable = o as ISpeciallySerializable; if (speciallySerializable != null) { var startingPosition = writer.Position; speciallySerializable.Save(writer); writer.Write(writer.Position - startingPosition); return(true); } if (type.IsArray) { var elementType = type.GetElementType(); var array = o as Array; var rank = array.Rank; writer.Write(rank); WriteArray(elementType, array); return(true); } var mDelegate = o as MulticastDelegate; if (mDelegate != null) { // if the target is trasient, we omit associated delegate entry var invocationList = GetDelegatesWithNonTransientTargets(mDelegate); writer.Write(invocationList.Length); foreach (var del in invocationList) { WriteField(typeof(object), del.Target); TouchAndWriteMethodId(del.Method); } return(true); } var str = o as string; if (str != null) { writer.Write(str); return(true); } if (!treatCollectionAsUserObject) { CollectionMetaToken collectionToken; if (CollectionMetaToken.TryGetCollectionMetaToken(o.GetType(), out collectionToken)) { // here we can have normal or extension method that needs to be treated differently int count = collectionToken.CountMethod.IsStatic ? (int)collectionToken.CountMethod.Invoke(null, new[] { o }) : (int)collectionToken.CountMethod.Invoke(o, null); if (collectionToken.IsDictionary) { WriteDictionary(collectionToken, count, o); } else { WriteEnumerable(collectionToken.FormalElementType, count, (IEnumerable)o); } return(true); } } return(false); }