public void ConstructorWithIndexedValues() { IASValue[] indexedValues = new IASValue[] { null, null, null }; ASArray array = new ASArray(indexedValues); Assert.AreSame(indexedValues, array.IndexedValues); Assert.AreEqual(0, array.DynamicProperties.Count); }
public void Reset() { classDefinitionCache.Clear(); objectReferenceCache.Clear(); stringReferenceCache.Clear(); currentValue = null; }
public void ConstructorWithIndexedAndMixedValues() { IASValue[] indexedValues = new IASValue[] { null, null, null }; IDictionary<string, IASValue> mixedValues = new Dictionary<string, IASValue>(); ASArray array = new ASArray(indexedValues, mixedValues); Assert.AreSame(indexedValues, array.IndexedValues); Assert.AreSame(mixedValues, array.DynamicProperties); }
public void WriteObject(IASValue value) { if (value == null) { WriteNull(); return; } // Check if we have seen the object reference before. CacheItem cacheItem; if (objectReferenceCache.TryGetValue(value, out cacheItem)) { WriteCachedValue(cacheItem); return; } // Otherwise write it out fresh. currentValue = value; value.AcceptVisitor(output.Serializer, this); currentValue = null; }
private IASValue ReadArray() { int bits = input.ReadVWInt29(); int lengthOrReferenceId = bits >> 1; // Handle cached objects. if ((bits & 1) == 0) { return GetObjectFromCache(AMF3ObjectTypeCode.Array, lengthOrReferenceId); } // Read out the whole array. if (lengthOrReferenceId < 0) throw new AMFException(String.Format(CultureInfo.CurrentCulture, ExceptionPrefix + "Encountered Array token with invalid length '{0}'.", lengthOrReferenceId)); // Important: Add the array to the cache before deserializing its properties! ASArray result = ASArray.CreateUninitializedInstance(); AddObjectToCache(AMF3ObjectTypeCode.Array, result); // Read mixed values if any. IDictionary<string, IASValue> mixedValues; string key = ReadStringData(); if (key.Length != 0) { mixedValues = new Dictionary<string, IASValue>(); for (; ; ) { IASValue value = ReadObject(); mixedValues.Add(key, value); key = ReadStringData(); if (key.Length == 0) break; } } else { mixedValues = EmptyDictionary<string, IASValue>.Instance; } // Read indexed values if any. IASValue[] indexedValues; if (lengthOrReferenceId != 0) { indexedValues = new IASValue[lengthOrReferenceId]; for (int i = 0; i < lengthOrReferenceId; i++) indexedValues[i] = ReadObject(); } else { indexedValues = EmptyArray<IASValue>.Instance; } result.SetProperties(indexedValues, mixedValues); return result; }
public void AddResultResponse(string responseTarget, object content) { IASValue asContent = context.Serializer.ToASValue(content); AddBody(new AMFBody(responseTarget + ResultTargetSuffix, "null", asContent)); }
/// <summary> /// Sets a mapped property or field value using reflection. /// </summary> /// <param name="serializer"></param> /// <param name="instance"></param> /// <param name="propertyOrField"></param> /// <param name="value"></param> private static void SetMappedPropertyOrField(IActionScriptSerializer serializer, object instance, MemberInfo propertyOrField, IASValue value) { try { // Try to set the property. PropertyInfo property = propertyOrField as PropertyInfo; if (property != null) { object propertyValue = serializer.ToNative(value, property.PropertyType); property.SetValue(instance, propertyValue, null); return; } // Oh, it must be a field then. FieldInfo field = (FieldInfo)propertyOrField; object fieldValue = serializer.ToNative(value, field.FieldType); field.SetValue(instance, fieldValue); } catch (Exception ex) { throw new ActionScriptException(String.Format(CultureInfo.CurrentCulture, "Error while setting value of property or field named '{0}' on class '{1}'", propertyOrField.Name, propertyOrField.ReflectedType.FullName), ex); } }
/// <summary> /// Converts the ActionScript value to a native value of the specified type. /// </summary> /// <remarks> /// The default implementation visits the <paramref name="asValue"/> and forwards the /// data to one of the specialized MapToXXX methods accordingly. /// </remarks> /// <param name="serializer">The serializer to use</param> /// <param name="asValue">The ActionScript value to convert</param> /// <param name="nativeType">The native type to produce</param> /// <returns>The native value</returns> /// <exception cref="ActionScriptException">Thrown if the mapping is not supported</exception> public virtual object ToNative(IActionScriptSerializer serializer, IASValue asValue, Type nativeType) { Visitor visitor = new Visitor(this, nativeType); asValue.AcceptVisitor(serializer, visitor); return visitor.Result; }
/// <summary> /// Creates an AMF header. /// </summary> /// <param name="name">The name of the header</param> /// <param name="mustUnderstand">A flag that indicates whether the remote host must understand the header</param> /// <param name="content">The content of the header</param> public AMFHeader(string name, bool mustUnderstand, IASValue content) { this.name = name; this.mustUnderstand = mustUnderstand; this.content = content; }
private IASValue ReadArray() { int length = input.ReadInt(); if (length < 0) throw new AMFException(ExceptionPrefix + "Encountered negative Array length."); // Important: Add the array to the cache before deserializing its properties! ASArray result = ASArray.CreateUninitializedInstance(); AddObjectToCache(result); IASValue[] indexedValues; // Read indexed values, if any. if (length != 0) { indexedValues = new IASValue[length]; for (int i = 0; i < length; i++) indexedValues[i] = ReadObject(); } else { indexedValues = EmptyArray<IASValue>.Instance; } result.SetProperties(indexedValues, EmptyDictionary<string, IASValue>.Instance); return result; }
public CacheItem(AMF3ObjectTypeCode objectType, IASValue obj) { this.ObjectType = objectType; this.Object = obj; }
/// <summary> /// Adds the specified object to the reference cache. /// </summary> /// <param name="objectType">The type of object to cache</param> /// <param name="obj">The object to cache</param> private void AddObjectToCache(AMF3ObjectTypeCode objectType, IASValue obj) { objectReferenceCache.Add(new CacheItem(objectType, obj)); }
private IASValue ReadObjectValue() { int bits = input.ReadVWInt29(); // Handle cached objects. if ((bits & 1) == 0) { int referenceId = bits >> 1; return(GetObjectFromCache(AMF3ObjectTypeCode.Object, referenceId)); } // Handle cached class definitions. ASClass classDefinition; if ((bits & 2) == 0) { int referenceId = bits >> 2; // Note: Object might be an ASExternalizableObject. IASValue obj = GetObjectFromCache(AMF3ObjectTypeCode.Object, referenceId); classDefinition = obj.Class; } else { // Read the class definition. ASClassLayout classLayout = (ASClassLayout)((bits & 0x0c) >> 2); if (classLayout > ASClassLayout.Dynamic) { throw new AMFException(String.Format(CultureInfo.CurrentCulture, ExceptionPrefix + "Encountered Object token with invalid class layout '{0}'.", classLayout)); } int memberCount = bits >> 4; if (memberCount < 0) { throw new AMFException(String.Format(CultureInfo.CurrentCulture, ExceptionPrefix + "Encountered Object token with invalid member count '{0}'.", memberCount)); } if (classLayout == ASClassLayout.Externalizable && memberCount != 0) { throw new AMFException(String.Format(CultureInfo.CurrentCulture, ExceptionPrefix + "Encountered Object token with Externalizable class layout and non-zero member count '{0}'.", memberCount)); } string classAlias = ReadStringData(); string[] memberNames; if (memberCount != 0) { memberNames = new string[memberCount]; for (int i = 0; i < memberCount; i++) { memberNames[i] = ReadStringData(); } } else { memberNames = EmptyArray <string> .Instance; } // Look up the class in the cache. classDefinition = ASClassCache.GetClass(classAlias, classLayout, memberNames); } // Read the instance data. if (classDefinition.Layout == ASClassLayout.Externalizable) { // Important: Add the object to the cache before deserializing its properties! ASExternalizableObject result = ASExternalizableObject.CreateUninitializedInstance(classDefinition); AddObjectToCache(AMF3ObjectTypeCode.Object, result); // Use custom serialization for the externalizable object. IExternalizable externalizableValue = input.Serializer.CreateExternalizableInstance(classDefinition.ClassAlias); externalizableValue.ReadExternal(input); result.SetProperties(externalizableValue); return(result); } else { // Important: Add the object to the cache before deserializing its properties! ASObject result = ASObject.CreateUninitializedInstance(classDefinition); AddObjectToCache(AMF3ObjectTypeCode.Object, result); // Read the member values. int memberCount = classDefinition.MemberNames.Count; IASValue[] memberValues; if (memberCount != 0) { memberValues = new IASValue[memberCount]; for (int i = 0; i < memberCount; i++) { memberValues[i] = ReadObject(); } } else { memberValues = EmptyArray <IASValue> .Instance; } // Read the dynamic property values. IDictionary <string, IASValue> dynamicProperties; if (classDefinition.Layout == ASClassLayout.Dynamic) { string key = ReadStringData(); if (key.Length != 0) { dynamicProperties = new Dictionary <string, IASValue>(); for (; ;) { IASValue value = ReadObject(); dynamicProperties.Add(key, value); key = ReadStringData(); if (key.Length == 0) { break; } } } else { dynamicProperties = EmptyDictionary <string, IASValue> .Instance; } } else { dynamicProperties = EmptyDictionary <string, IASValue> .Instance; } result.SetProperties(memberValues, dynamicProperties); return(result); } }
private IASValue ReadArray() { int bits = input.ReadVWInt29(); int lengthOrReferenceId = bits >> 1; // Handle cached objects. if ((bits & 1) == 0) { return(GetObjectFromCache(AMF3ObjectTypeCode.Array, lengthOrReferenceId)); } // Read out the whole array. if (lengthOrReferenceId < 0) { throw new AMFException(String.Format(CultureInfo.CurrentCulture, ExceptionPrefix + "Encountered Array token with invalid length '{0}'.", lengthOrReferenceId)); } // Important: Add the array to the cache before deserializing its properties! ASArray result = ASArray.CreateUninitializedInstance(); AddObjectToCache(AMF3ObjectTypeCode.Array, result); // Read mixed values if any. IDictionary <string, IASValue> mixedValues; string key = ReadStringData(); if (key.Length != 0) { mixedValues = new Dictionary <string, IASValue>(); for (; ;) { IASValue value = ReadObject(); mixedValues.Add(key, value); key = ReadStringData(); if (key.Length == 0) { break; } } } else { mixedValues = EmptyDictionary <string, IASValue> .Instance; } // Read indexed values if any. IASValue[] indexedValues; if (lengthOrReferenceId != 0) { indexedValues = new IASValue[lengthOrReferenceId]; for (int i = 0; i < lengthOrReferenceId; i++) { indexedValues[i] = ReadObject(); } } else { indexedValues = EmptyArray <IASValue> .Instance; } result.SetProperties(indexedValues, mixedValues); return(result); }
public void Reset() { referenceCache.Clear(); currentValue = null; }
/// <summary> /// Sets a mapped property or field value using reflection. /// </summary> /// <param name="serializer"></param> /// <param name="instance"></param> /// <param name="propertyOrField"></param> /// <param name="value"></param> private static void SetMappedPropertyOrField(IActionScriptSerializer serializer, object instance, MemberInfo propertyOrField, IASValue value) { try { // Try to set the property. PropertyInfo property = propertyOrField as PropertyInfo; if (property != null) { object propertyValue = serializer.ToNative(value, property.PropertyType); property.SetValue(instance, propertyValue, null); return; } // Oh, it must be a field then. FieldInfo field = (FieldInfo)propertyOrField; object fieldValue = serializer.ToNative(value, field.FieldType); field.SetValue(instance, fieldValue); } catch (Exception ex) { throw new ActionScriptException(String.Format(CultureInfo.CurrentCulture, "Error while setting value of property or field named '{0}' on class '{1}'", propertyOrField.Name, propertyOrField.ReflectedType.FullName), ex); } }
/// <summary> /// Sets a mapped property or field value or a dynamic property depending on the mapping. /// </summary> /// <param name="serializer"></param> /// <param name="instance"></param> /// <param name="dynamic"></param> /// <param name="propertyName"></param> /// <param name="value"></param> private void SetMappedMemberOrDynamicProperty(IActionScriptSerializer serializer, object instance, IDynamic dynamic, string propertyName, IASValue value) { // Set the mapped property, if there is one. ActionScriptPropertyMapping propertyMapping; if (propertyMappings.TryGetValue(propertyName, out propertyMapping)) { SetMappedPropertyOrField(serializer, instance, propertyMapping.NativePropertyOrField, value); // If the property is dynamic then also set it as a dynamic property if possible. if (dynamic != null && propertyMapping.IsDynamic) { SetDynamicProperty(dynamic, serializer, propertyName, value); } } else if (dynamic != null) { SetDynamicProperty(dynamic, serializer, propertyName, value); } else { throw new ActionScriptException(String.Format(CultureInfo.CurrentCulture, "Unable to set value for property '{0}' during ActionScript object deserialization because no suitable mapping is defined and type '{1}' is not dynamic.", propertyName, classMapping.NativeType.FullName)); } }
private static void SetDynamicProperty(IDynamic dynamic, IActionScriptSerializer serializer, string propertyName, IASValue value) { try { dynamic.SetDynamicProperty(serializer, propertyName, value); } catch (Exception ex) { throw new ActionScriptException(String.Format(CultureInfo.CurrentCulture, "Error while setting value of dynamic property '{0}' on class '{1}'", propertyName, dynamic.GetType().FullName), ex); } }
private IASValue ReadObjectValue() { int bits = input.ReadVWInt29(); // Handle cached objects. if ((bits & 1) == 0) { int referenceId = bits >> 1; return GetObjectFromCache(AMF3ObjectTypeCode.Object, referenceId); } // Handle cached class definitions. ASClass classDefinition; if ((bits & 2) == 0) { int referenceId = bits >> 2; // Note: Object might be an ASExternalizableObject. IASValue obj = GetObjectFromCache(AMF3ObjectTypeCode.Object, referenceId); classDefinition = obj.Class; } else { // Read the class definition. ASClassLayout classLayout = (ASClassLayout) ((bits & 0x0c) >> 2); if (classLayout > ASClassLayout.Dynamic) throw new AMFException(String.Format(CultureInfo.CurrentCulture, ExceptionPrefix + "Encountered Object token with invalid class layout '{0}'.", classLayout)); int memberCount = bits >> 4; if (memberCount < 0) throw new AMFException(String.Format(CultureInfo.CurrentCulture, ExceptionPrefix + "Encountered Object token with invalid member count '{0}'.", memberCount)); if (classLayout == ASClassLayout.Externalizable && memberCount != 0) throw new AMFException(String.Format(CultureInfo.CurrentCulture, ExceptionPrefix + "Encountered Object token with Externalizable class layout and non-zero member count '{0}'.", memberCount)); string classAlias = ReadStringData(); string[] memberNames; if (memberCount != 0) { memberNames = new string[memberCount]; for (int i = 0; i < memberCount; i++) memberNames[i] = ReadStringData(); } else { memberNames = EmptyArray<string>.Instance; } // Look up the class in the cache. classDefinition = ASClassCache.GetClass(classAlias, classLayout, memberNames); } // Read the instance data. if (classDefinition.Layout == ASClassLayout.Externalizable) { // Important: Add the object to the cache before deserializing its properties! ASExternalizableObject result = ASExternalizableObject.CreateUninitializedInstance(classDefinition); AddObjectToCache(AMF3ObjectTypeCode.Object, result); // Use custom serialization for the externalizable object. IExternalizable externalizableValue = input.Serializer.CreateExternalizableInstance(classDefinition.ClassAlias); externalizableValue.ReadExternal(input); result.SetProperties(externalizableValue); return result; } else { // Important: Add the object to the cache before deserializing its properties! ASObject result = ASObject.CreateUninitializedInstance(classDefinition); AddObjectToCache(AMF3ObjectTypeCode.Object, result); // Read the member values. int memberCount = classDefinition.MemberNames.Count; IASValue[] memberValues; if (memberCount != 0) { memberValues = new IASValue[memberCount]; for (int i = 0; i < memberCount; i++) memberValues[i] = ReadObject(); } else { memberValues = EmptyArray<IASValue>.Instance; } // Read the dynamic property values. IDictionary<string, IASValue> dynamicProperties; if (classDefinition.Layout == ASClassLayout.Dynamic) { string key = ReadStringData(); if (key.Length != 0) { dynamicProperties = new Dictionary<string, IASValue>(); for (; ; ) { IASValue value = ReadObject(); dynamicProperties.Add(key, value); key = ReadStringData(); if (key.Length == 0) break; } } else { dynamicProperties = EmptyDictionary<string, IASValue>.Instance; } } else { dynamicProperties = EmptyDictionary<string, IASValue>.Instance; } result.SetProperties(memberValues, dynamicProperties); return result; } }
/// <summary> /// Adds the specified object to the reference cache. /// </summary> /// <param name="objectType">The type of object to cache</param> /// <param name="obj">The object to cache</param> private void AddObjectToCache(AMF3ObjectTypeCode objectType, IASValue obj) { objectReferenceCache.Add(new CacheItem(objectType, obj)); }
public CacheItem(AMF3ObjectTypeCode objectType, IASValue obj) { this.ObjectType = objectType; this.Object = obj; }
/// <summary> /// Writes AMF content. /// </summary> /// <param name="output">The output stream</param> /// <param name="content">The content to write</param> private static void WriteAMFContent(AMFDataOutput output, IASValue content) { output.BeginObjectStream(); try { output.WriteObject(content); } finally { output.EndObjectStream(); } }
protected T ToNative <T>(IASValue asValue) { return((T)serializer.ToNative(asValue, typeof(T))); }
/// <summary> /// Adds the specified object to the reference cache. /// </summary> /// <param name="obj">The object to cache</param> private void AddObjectToCache(IASValue obj) { objectReferenceCache.Add(obj); }
/// <summary> /// Creates an AMF header. /// </summary> /// <param name="name">The name of the header</param> /// <param name="mustUnderstand">A flag that indicates whether the remote host must understand the header</param> /// <param name="content">The content of the header</param> public AMFHeader(string name, bool mustUnderstand, IASValue content) { this.name = name; this.mustUnderstand = mustUnderstand; this.content = content; }
/// <summary> /// Creates an AMF body. /// </summary> /// <param name="requestTarget">The target of the message body</param> /// <param name="responseTarget">The response target of the message body, or the string "null" if none</param> /// <param name="content">The content of the body</param> public AMFBody(string requestTarget, string responseTarget, IASValue content) { this.requestTarget = requestTarget; this.responseTarget = responseTarget; this.content = content; }
/// <inheritdoc /> public void WriteObject(IASValue value) { if (!inObjectStream) throw new InvalidOperationException("WriteObject cannot be called except while writing an object stream."); objectWriter.WriteObject(value); }
/// <summary> /// Creates an AMF body. /// </summary> /// <param name="requestTarget">The target of the message body</param> /// <param name="responseTarget">The response target of the message body, or the string "null" if none</param> /// <param name="content">The content of the body</param> public AMFBody(string requestTarget, string responseTarget, IASValue content) { this.requestTarget = requestTarget; this.responseTarget = responseTarget; this.content = content; }
/// <summary> /// Sets a mapped property or field value or a dynamic property depending on the mapping. /// </summary> /// <param name="serializer"></param> /// <param name="instance"></param> /// <param name="dynamic"></param> /// <param name="propertyName"></param> /// <param name="value"></param> private void SetMappedMemberOrDynamicProperty(IActionScriptSerializer serializer, object instance, IDynamic dynamic, string propertyName, IASValue value) { // Set the mapped property, if there is one. ActionScriptPropertyMapping propertyMapping; if (propertyMappings.TryGetValue(propertyName, out propertyMapping)) { SetMappedPropertyOrField(serializer, instance, propertyMapping.NativePropertyOrField, value); // If the property is dynamic then also set it as a dynamic property if possible. if (dynamic != null && propertyMapping.IsDynamic) { SetDynamicProperty(dynamic, serializer, propertyName, value); } } else if (dynamic != null) { SetDynamicProperty(dynamic, serializer, propertyName, value); } else { throw new ActionScriptException(String.Format(CultureInfo.CurrentCulture, "Unable to set value for property '{0}' during ActionScript object deserialization because no suitable mapping is defined and type '{1}' is not dynamic.", propertyName, classMapping.NativeType.FullName)); } }