public void TypelessWriteVectorObject(IList vector) { if (WriteVectorHeader(vector, (uint)vector.Count, true)) { return; } // get type of vector element Type elementType = vector.GetType().GetGenericArguments()[0]; // get class info for type string alias = Amf3ClassDef.GetAliasFromType(elementType); // get alias of vector element from info if (alias == null) { alias = elementType.FullName; } // write vector element class alias TypelessWrite(alias); foreach (object i in vector) { Write(i); } }
private IAmf3Serializer GetSerializerForType(System.Type type) { IAmf3Serializer serializer; if (!typeToSerializer.TryGetValue(type, out serializer)) { var alias = Amf3ClassDef.GetAliasFromType(type); if (alias != null) { serializer = Amf3ClassDef.GetSerializerFromAlias(alias); if (serializer == null) { // create reflection serializer serializer = new ReflectionSerializer(alias, type, true, false); // automatically register it Amf3ClassDef.RegisterSerializer(alias, serializer); } } else { // create anonymous serializer serializer = new ReflectionSerializer("*", type, true, false); } // store serializer in our local cache typeToSerializer.Add(type, serializer); } return(serializer); }
private Amf3ClassDef ReadAmf3ClassDef(Amf3Object.Flags flags) { bool externalizable = ((flags & Amf3Object.Flags.Externalizable) != 0); bool dynamic = ((flags & Amf3Object.Flags.Dynamic) != 0); string name = ReadString(); if (externalizable && dynamic) { throw new InvalidOperationException("Serialized objects cannot be both dynamic and externalizable"); } List <string> properties = new List <string>(); int members = ((int)flags) >> 4; for (int i = 0; i < members; i++) { properties.Add(ReadString()); } Amf3ClassDef classDef = new Amf3ClassDef(name, properties.ToArray(), dynamic, externalizable); // lookup serializer to use for this class definition classDef.Serializer = GetSerializerFromAlias(classDef.Name); traitTable.Add(classDef); return(classDef); }
public object NewInstance(Amf3ClassDef classDef) { var expando = new ExpandoObject(classDef.Properties.Length); // assign class definition to expando object expando.ClassDefinition = classDef; return(expando); }
public Amf3Object(Amf3ClassDef classDef) { if (classDef == null) { throw new ArgumentNullException("classDef"); } ClassDef = classDef; Properties = new Dictionary <string, object>(); }
public static void EmitAllSerializerCode(TextWriter tw, Func<System.Type, Mode> modeSelector) { var list = Amf3ClassDef.GetAllRegisteredTypes(); foreach (var kvp in list) { // apply filter var mode = modeSelector(kvp.Value); if (mode != Mode.Skip) { EmitSerializerCode(tw, mode, kvp.Key, kvp.Value); } } }
public Amf3Object(Amf3ClassDef classDef) { if (classDef == null) { throw new ArgumentNullException("classDef"); } // set class definition ClassDef = classDef; // allocate property values Values = new Variant[classDef.Properties.Length]; }
public void TypelessWrite(Amf3ClassDef classDef) { // have we written this class before with this writer? if (classDef.mWriter == this) { // use the cached id in the class definition TypelessWrite((classDef.mId << 2) | 1); return; } int index; if (classDefTable.TryGetValue(classDef, out index)) { // store class id inside of class def for this writer classDef.mWriter = this; classDef.mId = index; TypelessWrite((index << 2) | 1); } else { // store class id inside of class def for this writer classDef.mWriter = this; classDef.mId = classDefTable.Count; // store class reference in lookup table classDefTable[classDef] = classDef.mId; Amf3Object.Flags flags = Amf3Object.Flags.Inline | Amf3Object.Flags.InlineClassDef; if (classDef.Externalizable) { flags |= Amf3Object.Flags.Externalizable; } if (classDef.Dynamic) { flags |= Amf3Object.Flags.Dynamic; } TypelessWrite((int)flags | (classDef.Properties.Length << 4)); TypelessWrite(classDef.Name); foreach (string i in classDef.Properties) { TypelessWrite(i); } } }
// gets serializer for a class alias string private IAmf3Serializer GetSerializerFromAlias(string alias) { IAmf3Serializer serializer = Amf3ClassDef.GetSerializerFromAlias(alias); if (serializer == null) { var type = Amf3ClassDef.GetTypeFromAlias(alias); if (type != null) { // create reflection serializer serializer = new ReflectionSerializer(alias, type, true, false); // automatically register it Amf3ClassDef.RegisterSerializer(alias, serializer); } } return(serializer); }
public void TypelessWrite(ExpandoObject obj) { // this allows for the sharing of expando values easily var redirect = obj.ClassDefinition as ExpandoObject; if (redirect != null) { TypelessWrite(redirect); return; } if (CheckObjectTable(obj)) { return; } // get class definition from expando Amf3ClassDef classDef = obj.ClassDefinition as Amf3ClassDef; if (classDef == null) { classDef = anonClassDef; } TypelessWrite(classDef); StoreObject(obj); foreach (string i in classDef.Properties) { Write(obj[i]); } if (classDef.Dynamic) { foreach (var kvp in obj) { TypelessWrite(kvp.Key); Write(kvp.Value); } TypelessWrite(""); } }
public object NewInstance(Amf3ClassDef classDef) { // First, we look the default constrcutor ConstructorInfo constructor = mType.GetConstructor(Type.EmptyTypes); if (constructor != null) { return(constructor.Invoke(null)); } // If there was no default constructor, use a constructor that only has default values ConstructorInfo[] allConstructors = mType.GetConstructors(); foreach (ConstructorInfo oneConstructor in allConstructors) { ParameterInfo[] parameters = oneConstructor.GetParameters(); if (parameters.Length == 0) { // Why did we not get this with the default constructor? // In any case, handle the case gracefully } else if (parameters[0].IsOptional) { // First parameter is optional, so all others are too, this constructor is good enough } else { // We can't use this constructor, try the next one continue; } object[] arguments = new object[parameters.Length]; for (int i = 0; i < parameters.Length; ++i) { arguments[i] = parameters[i].DefaultValue; } return(oneConstructor.Invoke(arguments)); } // Did we miss something? throw new NotSupportedException(); }
public ReflectionSerializer(string alias, System.Type type, bool addFields = true, bool addProperties = true) { if (alias == null || type == null) { throw new ArgumentNullException(); } mType = type; mVectorType = typeof(_root.Vector <>).MakeGenericType(new Type[1] { mType }); var properties = new List <string>(); // get all instance fields of type (public or private) mFieldList = new List <FieldInfo>(); if (addFields) { foreach (var field in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { mFieldList.Add(field); properties.Add(field.Name); } } // get all instance properties of type (public or private) mPropertyList = new List <PropertyInfo>(); if (addProperties) { foreach (var prop in type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { mPropertyList.Add(prop); properties.Add(prop.Name); } } // create class definition from member list // this defines the property ordering mClassDef = new Amf3ClassDef(alias, properties.ToArray()); }
// begins the reading of a new object // the classdef passed in here will define the ordering of the subsequent property reads public void ReadObjectHeader(Amf3ClassDef serializerClassDef) { // did serializer definition change? if (mSerializerClassDef != serializerClassDef) { // set new serializer definition mNames = serializerClassDef.Properties; mSerializerClassDef = serializerClassDef; // build remap table from the serializer properties to stream properties mSerializerRemapTable = new int[mNames.Length]; if (!mStreamClassDef.Equals(serializerClassDef)) { // mapping is required, create remap table for (int i = 0; i < mSerializerRemapTable.Length; i++) { // get stream property index int streamIndex = mStreamClassDef.GetPropertyIndex(mNames[i]); // store in remap table mSerializerRemapTable[i] = streamIndex + 1; } } else { // no remapping required, create direct mapped table for (int i = 0; i < mSerializerRemapTable.Length; i++) { mSerializerRemapTable[i] = i + 1; } } } // begin reading using remap table mRemapTable = mSerializerRemapTable; mReadIndex = 0; mReadCount = mRemapTable.Length; }
// this function generates AMF class definitions for all dynamic (expando) objects it finds and assigns them to the ClassDefinition property of Expando // it does this by generating a class definition for each unique property list // having shared class definitions will result in a much more compact serialized form public static void GenerateAndApplyClassDefinitions(object root, bool keepExistingAlias = true) { var expandos = new List <ExpandoObject>(); var classDefs = new Dictionary <string, Amf3ClassDef>(); // visit all expando objects in graph and apply class definitions VisitAllExpandoObjects(root, (expando) => { // get properties from expando var properties = new List <String>(); foreach (var kvp in expando) { properties.Add(kvp.Key); } // sort properties properties.Sort(); string alias = "*"; if (keepExistingAlias && expando.ClassDefinition != null) { var existingClassDef = expando.ClassDefinition as Amf3ClassDef; if (existingClassDef != null) { alias = existingClassDef.Name; } else { var existingClassAlias = expando.ClassDefinition as string; if (existingClassAlias != null) { alias = existingClassAlias; } } } // create class definition from properties var expandoDef = new Amf3ClassDef(alias, properties.ToArray()); // see if a class definition already exists for these properties... Amf3ClassDef classDef; if (!classDefs.TryGetValue(expandoDef.Hash, out classDef)) { // register new class definition classDef = expandoDef; classDefs.Add(classDef.Hash, classDef); if (Verbose) { Console.WriteLine("AMF3 generated class: {0}", classDef.Hash); } } // set class definition for expando object expando.ClassDefinition = classDef; } ); if (Verbose) { Console.WriteLine("AMF3 expandos: {0} classDefs: {1}", expandos.Count, classDefs.Count); } }
public void WriteObjectHeader(Amf3ClassDef classDef, object obj = null) { Write(Amf3TypeCode.Object); TypelessWrite(classDef); StoreObject(obj); }
internal Amf3Reader(Amf3ClassDef streamClassDef) { mStreamClassDef = streamClassDef; mValues = new Variant[streamClassDef.Properties.Length + 1]; // +1 for undefined property 0 mNames = streamClassDef.Properties; }
public Amf3Object ReadAmf3Object() { Amf3Object.Flags flags = (Amf3Object.Flags)ReadInteger(); if ((flags & Amf3Object.Flags.Inline) == 0) { return((Amf3Object)GetTableEntry(objectTable, ((int)flags) >> 1)); } Amf3ClassDef classDef; if ((flags & Amf3Object.Flags.InlineClassDef) == 0) { classDef = GetTableEntry(traitTable, ((int)flags) >> 2); } else { bool externalizable = ((flags & Amf3Object.Flags.Externalizable) != 0); bool dynamic = ((flags & Amf3Object.Flags.Dynamic) != 0); string name = ReadString(); if (externalizable && dynamic) { throw new InvalidOperationException("Serialized objects cannot be both dynamic and externalizable"); } List <string> properties = new List <string>(); int members = ((int)flags) >> 4; for (int i = 0; i < members; i++) { properties.Add(ReadString()); } classDef = new Amf3ClassDef(name, properties, dynamic, externalizable); traitTable.Add(classDef); } Amf3Object obj = new Amf3Object(classDef); objectTable.Add(obj); if (classDef.Externalizable) { obj.Properties["inner"] = ReadNextObject(); return(obj); } foreach (string i in classDef.Properties) { obj.Properties[i] = ReadNextObject(); } if (classDef.Dynamic) { string key = ReadString(); while (key != "") { obj.Properties[key] = ReadNextObject(); key = ReadString(); } } return(obj); }
public object NewInstance(Amf3ClassDef classDef) { return(new Amf3Object(classDef)); }