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);
                }
            }
        }
Exemple #3
0
        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);
        }