/// <summary> /// Creates an object with the specified class, member values and dynamic properties. /// </summary> /// <param name="class">The ActionScript class</param> /// <param name="memberValues">The member values of the object</param> /// <param name="dynamicProperties">The dynamic properties of the object</param> /// <exception cref="ArgumentNullException">Thrown if the <paramref name="class"/> is null /// (hint: use <see cref="ASClass.UntypedDynamicClass" /></exception> /// <exception cref="ArgumentNullException">Thrown when <paramref name="memberValues"/> or /// <paramref name="dynamicProperties"/> is null</exception> /// <exception cref="ArgumentException">Thrown if the layout of the class is not /// <see cref="ASClassLayout.Normal" /> or <see cref="ASClassLayout.Dynamic" /></exception> /// <exception cref="ArgumentException">Thrown if the number of members defined by the class /// differs from the count of <paramref name="memberValues"/></exception> public ASObject(ASClass @class, IList <IASValue> memberValues, IDictionary <string, IASValue> dynamicProperties) { if (@class == null) { throw new ArgumentNullException("class", "Class must not be null. Did you mean to use ASClass.UntypedDynamicClass?"); } if (memberValues == null) { throw new ArgumentNullException("memberValues"); } if (dynamicProperties == null) { throw new ArgumentNullException("properties"); } if (@class.Layout != ASClassLayout.Normal && @class.Layout != ASClassLayout.Dynamic) { throw new ArgumentException("The class layout must be Normal or Dynamic.", "class"); } if (@class.MemberNames.Count != memberValues.Count) { throw new ArgumentException("The number of member values provided must equal the number of members defined by the class.", "class"); } this.@class = @class; this.memberValues = memberValues; this.dynamicProperties = dynamicProperties; }
/// <inheritdoc /> public override bool Equals(object obj) { if (ReferenceEquals(this, obj)) { return(true); } ASClass other = obj as ASClass; if (other != null && other.classAlias == classAlias && other.layout == layout) { IList <string> otherMemberNames = other.memberNames; if (otherMemberNames == memberNames) { return(true); } int count = memberNames.Count; if (otherMemberNames.Count == count) { for (int i = 0; i < count; i++) { if (otherMemberNames[i] != memberNames[i]) { return(false); } } return(true); } } return(false); }
/// <summary> /// Creates an uninitialized object. /// </summary> /// <param name="class">The ActionScript class</param> /// <exception cref="ArgumentNullException">Thrown when <paramref name="class"/> is null</exception> private ASNativeObject(ASClass @class) { if (@class == null) throw new ArgumentNullException("class"); this.@class = @class; }
public override void SetUp() { base.SetUp(); externalizableClass = new ASClass("extern", ASClassLayout.Externalizable, EmptyArray<string>.Instance); externalizable = Mocks.CreateMock<IExternalizable>(); }
public void GetHashCodeIsSane() { // Compare hashcodes of two identical classes. ASClass class1 = new ASClass("abc", ASClassLayout.Dynamic, new string[] { "abc", "def" }); ASClass class2 = new ASClass("abc", ASClassLayout.Dynamic, new string[] { "abc", "def" }); Assert.AreEqual(class1.GetHashCode(), class2.GetHashCode()); }
public void Constructor(string className, ASClassLayout classLayout, string[] memberNames) { ASClass @class = new ASClass(className, classLayout, memberNames); Assert.AreSame(className, @class.ClassAlias); Assert.AreEqual(classLayout, @class.Layout); Assert.AreSame(memberNames, @class.MemberNames); }
/// <summary> /// Creates an uninitialized object. /// </summary> /// <param name="class">The ActionScript class</param> /// <param name="dummy">The value is ignored and is only used to disambiguate the constructor signature</param> /// <exception cref="ArgumentNullException">Thrown if the <paramref name="class"/> is null /// (hint: use <see cref="ASClass.UntypedDynamicClass" /></exception> /// <exception cref="ArgumentException">Thrown if the layout of the class is not /// <see cref="ASClassLayout.Normal" /> or <see cref="ASClassLayout.Dynamic" /></exception> private ASObject(ASClass @class, bool dummy) { if (@class == null) throw new ArgumentNullException("class", "Class must not be null. Did you mean to use ASClass.UntypedDynamicClass?"); if (@class.Layout != ASClassLayout.Normal && @class.Layout != ASClassLayout.Dynamic) throw new ArgumentException("The class layout must be Normal or Dynamic.", "class"); this.@class = @class; }
/// <summary> /// Creates an uninitialized object. /// </summary> /// <param name="class">The ActionScript class</param> /// <exception cref="ArgumentNullException">Thrown when <paramref name="class"/> is null</exception> private ASNativeObject(ASClass @class) { if (@class == null) { throw new ArgumentNullException("class"); } this.@class = @class; }
/// <summary> /// Creates an uninitialized object. /// </summary> /// <param name="class">The ActionScript class</param> /// <exception cref="ArgumentNullException">Thrown when <paramref name="class"/> is null</exception> /// <exception cref="ArgumentException">Thrown when the class layout of <paramref name="class"/> is /// not <see cref="ASClassLayout.Externalizable" /></exception> private ASExternalizableObject(ASClass @class) { if (@class == null) throw new ArgumentNullException("class"); if (@class.Layout != ASClassLayout.Externalizable) throw new ArgumentException("The class layout must be Externalizable.", "class"); this.@class = @class; }
/// <summary> /// Creates an object with the specified class and externalizable value. /// </summary> /// <param name="class">The ActionScript class</param> /// <param name="externalizableValue">The externalizable value</param> /// <exception cref="ArgumentNullException">Thrown when <paramref name="class"/> or <paramref name="externalizableValue"/> /// is null</exception> /// <exception cref="ArgumentException">Thrown when the class layout of <paramref name="class"/> is /// not <see cref="ASClassLayout.Externalizable" /></exception> public ASExternalizableObject(ASClass @class, IExternalizable externalizableValue) { if (@class == null) throw new ArgumentNullException("class"); if (externalizableValue == null) throw new ArgumentNullException("externalizableValue"); if (@class.Layout != ASClassLayout.Externalizable) throw new ArgumentException("The class layout must be Externalizable.", "class"); this.@class = @class; this.externalizableValue = externalizableValue; }
/// <summary> /// Creates an uninitialized object. /// </summary> /// <param name="class">The ActionScript class</param> /// <param name="dummy">The value is ignored and is only used to disambiguate the constructor signature</param> /// <exception cref="ArgumentNullException">Thrown if the <paramref name="class"/> is null /// (hint: use <see cref="ASClass.UntypedDynamicClass" /></exception> /// <exception cref="ArgumentException">Thrown if the layout of the class is not /// <see cref="ASClassLayout.Normal" /> or <see cref="ASClassLayout.Dynamic" /></exception> private ASObject(ASClass @class, bool dummy) { if (@class == null) { throw new ArgumentNullException("class", "Class must not be null. Did you mean to use ASClass.UntypedDynamicClass?"); } if (@class.Layout != ASClassLayout.Normal && @class.Layout != ASClassLayout.Dynamic) { throw new ArgumentException("The class layout must be Normal or Dynamic.", "class"); } this.@class = @class; }
/// <summary> /// Creates a wrapper for a native value. /// </summary> /// <param name="class">The ActionScript class</param> /// <param name="nativeObject">The native object</param> /// <param name="mapper">The mapper to use for mapping the object to ActionScript on demand</param> /// <exception cref="ArgumentNullException">Thrown when <paramref name="class"/>, <paramref name="nativeObject"/>, /// or <paramref name="mapper"/> is null</exception> public ASNativeObject(ASClass @class, object nativeObject, IASNativeObjectMapper mapper) { if (@class == null) throw new ArgumentNullException("class"); if (nativeObject == null) throw new ArgumentNullException("nativeObject"); if (mapper == null) throw new ArgumentNullException("mapper"); this.@class = @class; this.nativeObject = nativeObject; this.mapper = mapper; }
/// <summary> /// Creates an ActionScript class mapping. /// </summary> /// <param name="nativeType">The mapped native type</param> /// <param name="asClass">The mapped ActionScript class</param> /// <param name="properties">The property mappings</param> /// <exception cref="ArgumentNullException">Thrown if <paramref name="nativeType"/>, /// <paramref name="asClass"/> or <paramref name="properties"/> is null</exception> public ActionScriptClassMapping(Type nativeType, ASClass asClass, ICollection<ActionScriptPropertyMapping> properties) { if (nativeType == null) throw new ArgumentNullException("nativeType"); if (asClass == null) throw new ArgumentNullException("asClass"); if (properties == null) throw new ArgumentNullException("properties"); this.nativeType = nativeType; this.asClass = asClass; this.properties = properties; }
public void ConstructorWithClass(ASClassLayout classLayout, string[] memberNames) { ASClass @class = new ASClass("class", classLayout, memberNames); ASObject obj = new ASObject(@class); Assert.AreSame(@class, obj.Class); Assert.AreEqual(memberNames.Length, obj.MemberValues.Count); Assert.AreEqual(0, obj.DynamicProperties.Count); Assert.AreEqual(classLayout == ASClassLayout.Normal, obj.DynamicProperties.IsReadOnly); if (memberNames.Length == 0) Assert.IsTrue(obj.MemberValues.IsReadOnly); }
/// <summary> /// Creates an uninitialized object. /// </summary> /// <param name="class">The ActionScript class</param> /// <exception cref="ArgumentNullException">Thrown when <paramref name="class"/> is null</exception> /// <exception cref="ArgumentException">Thrown when the class layout of <paramref name="class"/> is /// not <see cref="ASClassLayout.Externalizable" /></exception> private ASExternalizableObject(ASClass @class) { if (@class == null) { throw new ArgumentNullException("class"); } if (@class.Layout != ASClassLayout.Externalizable) { throw new ArgumentException("The class layout must be Externalizable.", "class"); } this.@class = @class; }
/// <summary> /// Creates an object with the specified class and no member values or dynamic properties initially set. /// </summary> /// <remarks> /// The object will have a fixed-length list of member values with the same length as the /// list of member names defined by the class. /// /// The object will have a read-only empty dynamic property dictionary if its /// class layout is <see cref="ASClassLayout.Normal" />, otherwise it will have /// a read-write dictionary. /// </remarks> /// <param name="class">The ActionScript class</param> /// <exception cref="ArgumentNullException">Thrown if the <paramref name="class"/> is null /// (hint: use <see cref="ASClass.UntypedDynamicClass" /></exception> /// <exception cref="ArgumentException">Thrown if the layout of the class is not /// <see cref="ASClassLayout.Normal" /> or <see cref="ASClassLayout.Dynamic" /></exception> public ASObject(ASClass @class) { if (@class == null) { throw new ArgumentNullException("class", "Class must not be null. Did you mean to use ASClass.UntypedDynamicClass?"); } if (@class.Layout != ASClassLayout.Normal && @class.Layout != ASClassLayout.Dynamic) { throw new ArgumentException("The class layout must be Normal or Dynamic.", "class"); } this.@class = @class; this.memberValues = @class.MemberNames.Count != 0 ? new IASValue[@class.MemberNames.Count] : EmptyArray <IASValue> .Instance; this.dynamicProperties = @class.Layout == ASClassLayout.Dynamic ? new Dictionary <string, IASValue>() : EmptyDictionary <string, IASValue> .Instance; }
/// <summary> /// Gets a shared and read-only class definition with the specified properties. /// The class is cached for reuse in subsequent requests. /// </summary> /// <remarks> /// This method is safe for concurrent access. /// </remarks> /// <param name="classAlias">The class alias</param> /// <param name="classLayout">The class layout</param> /// <param name="memberNames">The class members</param> /// <returns>The shared class definition</returns> public static ASClass GetClass(string classAlias, ASClassLayout classLayout, IList<string> memberNames) { lock (cache) { // Yes we create a new class instance in order to search the cache. // However, if we do find a match we will not return it to the caller so it // will get promptly garbage collected. ASClass key = new ASClass(classAlias, classLayout, memberNames); ASClass @class; if (cache.TryGetValue(key, out @class)) return @class; cache.Add(key, key); return key; } }
/// <summary> /// Creates an object with the specified class and externalizable value. /// </summary> /// <param name="class">The ActionScript class</param> /// <param name="externalizableValue">The externalizable value</param> /// <exception cref="ArgumentNullException">Thrown when <paramref name="class"/> or <paramref name="externalizableValue"/> /// is null</exception> /// <exception cref="ArgumentException">Thrown when the class layout of <paramref name="class"/> is /// not <see cref="ASClassLayout.Externalizable" /></exception> public ASExternalizableObject(ASClass @class, IExternalizable externalizableValue) { if (@class == null) { throw new ArgumentNullException("class"); } if (externalizableValue == null) { throw new ArgumentNullException("externalizableValue"); } if (@class.Layout != ASClassLayout.Externalizable) { throw new ArgumentException("The class layout must be Externalizable.", "class"); } this.@class = @class; this.externalizableValue = externalizableValue; }
/// <summary> /// Gets a shared and read-only class definition with the specified properties. /// The class is cached for reuse in subsequent requests. /// </summary> /// <remarks> /// This method is safe for concurrent access. /// </remarks> /// <param name="classAlias">The class alias</param> /// <param name="classLayout">The class layout</param> /// <param name="memberNames">The class members</param> /// <returns>The shared class definition</returns> public static ASClass GetClass(string classAlias, ASClassLayout classLayout, IList <string> memberNames) { lock (cache) { // Yes we create a new class instance in order to search the cache. // However, if we do find a match we will not return it to the caller so it // will get promptly garbage collected. ASClass key = new ASClass(classAlias, classLayout, memberNames); ASClass @class; if (cache.TryGetValue(key, out @class)) { return(@class); } cache.Add(key, key); return(key); } }
/// <summary> /// Creates a wrapper for a native value. /// </summary> /// <param name="class">The ActionScript class</param> /// <param name="nativeObject">The native object</param> /// <param name="mapper">The mapper to use for mapping the object to ActionScript on demand</param> /// <exception cref="ArgumentNullException">Thrown when <paramref name="class"/>, <paramref name="nativeObject"/>, /// or <paramref name="mapper"/> is null</exception> public ASNativeObject(ASClass @class, object nativeObject, IASNativeObjectMapper mapper) { if (@class == null) { throw new ArgumentNullException("class"); } if (nativeObject == null) { throw new ArgumentNullException("nativeObject"); } if (mapper == null) { throw new ArgumentNullException("mapper"); } this.@class = @class; this.nativeObject = nativeObject; this.mapper = mapper; }
public void WriteObject_Objects_ClassDefinitionCaching_AMF3() { // Write out two untyped dynamic objects and two typed normal // objects and ensure the class definition is reused. ASObject untyped1 = new ASObject(); ASObject untyped2 = new ASObject(); ASClass @class = new ASClass("class", ASClassLayout.Normal, EmptyArray<string>.Instance); ASObject typed1 = new ASObject(@class); ASObject typed2 = new ASObject(@class); Mocks.ReplayAll(); output.ObjectEncoding = AMFObjectEncoding.AMF3; output.BeginObjectStream(); output.WriteObject(untyped1); output.WriteObject(typed1); output.WriteObject(untyped2); output.WriteObject(typed2); output.EndObjectStream(); byte[] expected = new byte[] { (byte)AMF0ObjectTypeCode.AMF3Data, (byte)AMF3ObjectTypeCode.Object, 0x0b, 0x01, 0x01, // untyped1 (byte)AMF3ObjectTypeCode.Object, 0x03, 0x0b, 0x63, 0x6c, 0x61, 0x73, 0x73, // typed1 (byte)AMF3ObjectTypeCode.Object, 0x01, 0x01, // untyped2 using cached class definition (byte)AMF3ObjectTypeCode.Object, 0x05, // typed2 using cached class definition }; CollectionAssert.AreElementsEqual(expected, stream.ToArray()); }
public void WriteObject_Objects_Externalizable_AMF3() { IExternalizable externalizableValue = Mocks.CreateMock<IExternalizable>(); externalizableValue.WriteExternal(output); LastCall.Do((WriteExternalDelegate)delegate(IDataOutput outputToUse) { // Note: outputToUse will be the same instance as output which we've already // tested so we don't need to try all combinations here. Just a few as a sanity check. outputToUse.WriteUTF("abc"); outputToUse.WriteInt(10); outputToUse.WriteObject(new ASString("def")); }); ASClass @class = new ASClass("class", ASClassLayout.Externalizable, EmptyArray<string>.Instance); ASExternalizableObject obj = new ASExternalizableObject(@class, externalizableValue); Mocks.ReplayAll(); output.ObjectEncoding = AMFObjectEncoding.AMF3; output.BeginObjectStream(); output.WriteObject(obj); output.EndObjectStream(); byte[] expected = new byte[] { (byte)AMF0ObjectTypeCode.AMF3Data, (byte)AMF3ObjectTypeCode.Object, 0x07, 0x0b, 0x63, 0x6c, 0x61, 0x73, 0x73, // class def 0x00, 0x03, 0x61, 0x62, 0x63, // write utf "abc" 0x00, 0x00, 0x00, 0x0a, // write int 10 (byte) AMF3ObjectTypeCode.String, 0x07, 0x64, 0x65, 0x66 // write object "def" }; CollectionAssert.AreElementsEqual(expected, stream.ToArray()); }
public void WriteObject_Objects(AMFObjectEncoding objectEncoding, byte[] expected, string className, ASClassLayout classLayout, string[] memberNames, string[] memberValues, string[] dynamicKeysAndValues) { ASClass @class = new ASClass(className, classLayout, memberNames); ASObject obj = new ASObject(@class, WrapStrings(memberValues), new Dictionary<string, IASValue>()); for (int i = 0; i < dynamicKeysAndValues.Length; i += 2) obj.DynamicProperties[dynamicKeysAndValues[i]] = new ASString(dynamicKeysAndValues[i + 1]); output.ObjectEncoding = objectEncoding; output.BeginObjectStream(); output.WriteObject(obj); output.EndObjectStream(); CollectionAssert.AreElementsEqual(expected, stream.ToArray()); }
public void WriteObject_Strings_Caching_AMF3() { ASString empty = new ASString(""); ASString valueA = new ASString("a"); ASString valueB = new ASString("b"); ASString valueC = new ASString("c"); ASXmlDocument xml = new ASXmlDocument(valueB.Value); ASArray array = new ASArray(new IASValue[] { valueA, valueB }); array.DynamicProperties[valueB.Value] = valueA; ASClass clazz = new ASClass(valueB.Value, ASClassLayout.Dynamic, new string[] { valueC.Value }); ASObject obj = new ASObject(clazz); obj.MemberValues[0] = valueC; obj.DynamicProperties[valueA.Value] = valueB; output.ObjectEncoding = AMFObjectEncoding.AMF3; output.BeginObjectStream(); output.WriteObject(empty); // empty strings are not cached output.WriteObject(valueA); // will get string ref #0 output.WriteObject(empty); // empty strings are not cached output.WriteObject(valueB); // will get string ref #1 output.WriteObject(valueA); // will use string ref #0 output.WriteObject(xml); // XML contents are same as valueB, will use ref #1 output.WriteObject(array); // Array contains valueA and valueB and mixed values with key valueB and value valueA output.WriteObject(obj); // Object has class name valueB contains member with key valueC and value valueA dynamic property with key valueA and value valueB output.EndObjectStream(); CollectionAssert.AreElementsEqual( new byte[] { (byte)AMF0ObjectTypeCode.AMF3Data, (byte)AMF3ObjectTypeCode.String, 0x01, // "" (byte)AMF3ObjectTypeCode.String, 0x03, 0x61, // valueA (byte)AMF3ObjectTypeCode.String, 0x01, // "" (byte)AMF3ObjectTypeCode.String, 0x03, 0x62, // valueB (byte)AMF3ObjectTypeCode.String, 0x00, // valueA (by ref) (byte)AMF3ObjectTypeCode.Xml, 0x02, // valueB (by ref) (byte)AMF3ObjectTypeCode.Array, 0x05, 0x02, (byte)AMF3ObjectTypeCode.String, 0x00, 0x01, (byte)AMF3ObjectTypeCode.String, 0x00, (byte)AMF3ObjectTypeCode.String, 0x02, // array (byte)AMF3ObjectTypeCode.Object, 0x1b, 0x02, 0x03, 0x63, (byte)AMF3ObjectTypeCode.String, 0x04, 0x00, (byte)AMF3ObjectTypeCode.String, 0x02, 0x01 // object }, stream.ToArray()); }
/// <summary> /// Creates an instance whose initialization is to be deferred. /// </summary> /// <remarks> /// This special case is used to resolve circular references during the construction of /// object graphs. The object should not be used until its properties have been initialized. /// </remarks> /// <param name="class">The ActionScript class</param> /// <exception cref="ArgumentNullException">Thrown when <paramref name="class"/> is null</exception> /// <returns>The uninitialized object</returns> public static ASNativeObject CreateUninitializedInstance(ASClass @class) { return new ASNativeObject(@class); }
public void Indexer() { ASClass @class = new ASClass("class", ASClassLayout.Dynamic, new string[] { "member" }); ASObject obj = new ASObject(@class); obj["member"] = new ASInt29(1); Assert.AreEqual(new ASInt29(1), obj["member"]); Assert.AreEqual(new ASInt29(1), obj.MemberValues[0]); obj["nonmember"] = new ASInt29(2); Assert.AreEqual(new ASInt29(2), obj["nonmember"]); Assert.AreEqual(new ASInt29(2), obj.DynamicProperties["nonmember"]); }
/// <summary> /// Creates an instance whose initialization is to be deferred. /// </summary> /// <remarks> /// This special case is used to resolve circular references during the construction of /// object graphs. The object should not be used until its properties have been initialized. /// </remarks> /// <param name="class">The ActionScript class</param> /// <returns>The uninitialized object</returns> /// <exception cref="ArgumentNullException">Thrown if the <paramref name="class"/> is null /// (hint: use <see cref="ASClass.UntypedDynamicClass" /></exception> /// <exception cref="ArgumentException">Thrown if the layout of the class is not /// <see cref="ASClassLayout.Normal" /> or <see cref="ASClassLayout.Dynamic" /></exception> public static ASObject CreateUninitializedInstance(ASClass @class) { return new ASObject(@class, false); }
public void ConstructorWithClassAndMemberValues(ASClassLayout classLayout, string[] memberNames, int[] memberValues) { IASValue[] asMemberValues = WrapInts(memberValues); ASClass @class = new ASClass("class", classLayout, memberNames); ASObject obj = new ASObject(@class, asMemberValues); Assert.AreSame(@class, obj.Class); Assert.AreSame(asMemberValues, obj.MemberValues); Assert.AreEqual(0, obj.DynamicProperties.Count); Assert.AreEqual(classLayout == ASClassLayout.Normal, obj.DynamicProperties.IsReadOnly); }
/// <summary> /// Creates an untyped dynamic object with no member values or dynamic properties initially set. /// </summary> /// <remarks> /// The object will have an empty read-only list of member values and a read-write /// dictionary of dynamic properties. /// </remarks> public ASObject() { this.@class = ASClass.UntypedDynamicClass; this.memberValues = EmptyArray<IASValue>.Instance; this.dynamicProperties = new Dictionary<string, IASValue>(); }
void IASValueVisitor.VisitObject(IActionScriptSerializer serializer, ASClass @class, IEnumerable<IASValue> memberValues, IEnumerable<KeyValuePair<string, IASValue>> dynamicProperties, IExternalizable externalizableValue) { int objectReferenceId = AddCurrentValueToCache(AMF3ObjectTypeCode.Object); output.WriteByte((byte)AMF3ObjectTypeCode.Object); // Look for a suitable existing class definition in the cache. int classDefinitionId; if (classDefinitionCache.TryGetValue(@class, out classDefinitionId)) { // Use class definition reference. output.WriteVWInt29(classDefinitionId * 4 + 1); } else { // Include class definition inline and add it to the cache. classDefinitionCache.Add(@class, objectReferenceId); output.WriteVWInt29(@class.MemberNames.Count * 16 + (int)@class.Layout * 4 + 3); WriteStringData(@class.ClassAlias); foreach (string memberName in @class.MemberNames) { if (String.IsNullOrEmpty(memberName)) throw new AMFException(ExceptionPrefix + "Cannot serialize an object with a null or empty member name."); WriteStringData(memberName); } } if (@class.Layout == ASClassLayout.Externalizable) { if (externalizableValue == null) throw new AMFException(ExceptionPrefix + "The class layout is Externalizable but the object does not provide an ExternalizableValue."); externalizableValue.WriteExternal(output); } else { // Write the members first as a sequence of values. int memberCount = @class.MemberNames.Count; int memberIndex = 0; foreach (IASValue memberValue in memberValues) { if (memberIndex == memberCount) throw new AMFException(ExceptionPrefix + "The number of member values provided by the object is greater than was indicated by its class."); WriteObject(memberValue); memberIndex += 1; } if (memberIndex != memberCount) throw new AMFException(ExceptionPrefix + "The number of member values provided by the object is less than was indicated by its class."); if (@class.Layout == ASClassLayout.Dynamic) { // Write dynamic key/value pairs. foreach (KeyValuePair<string, IASValue> pair in dynamicProperties) { if (String.IsNullOrEmpty(pair.Key)) throw new AMFException(ExceptionPrefix + "Cannot serialize an object with a null or empty string key."); WriteStringData(pair.Key); WriteObject(pair.Value); } // Terminate with empty string. WriteStringData(""); } } }
public void EqualsWithIdenticalInstancesIsTrue() { ASClass class1 = new ASClass("abc", ASClassLayout.Dynamic, new string[] { "abc", "def" }); ASClass class2 = new ASClass("abc", ASClassLayout.Dynamic, new string[] { "abc", "def" }); Assert.AreEqual(class1, class2); }
public void EqualsWithDifferentMemberOrderIsFalse() { ASClass class1 = new ASClass("abc", ASClassLayout.Dynamic, new string[] { "abc", "def" }); ASClass class2 = new ASClass("abc", ASClassLayout.Dynamic, new string[] { "def", "abc" }); Assert.AreNotEqual(class1, class2); }
private IASValue ReadObjectWithClass(ASClass classDefinition) { // Important: Add the object to the cache before deserializing its properties! ASObject result = ASObject.CreateUninitializedInstance(classDefinition); AddObjectToCache(result); IDictionary<string, IASValue> dynamicProperties; // Read dynamic properties, if any. string key = input.ReadShortString(); if (key.Length != 0) { dynamicProperties = new Dictionary<string, IASValue>(); for (; ; ) { IASValue value = input.ReadObject(); dynamicProperties.Add(key, value); key = input.ReadShortString(); if (key.Length == 0) break; } } else { dynamicProperties = EmptyDictionary<string, IASValue>.Instance; } ConsumeEndOfObject(); result.SetProperties(EmptyArray<IASValue>.Instance, dynamicProperties); return result; }
/// <summary> /// Creates an instance whose initialization is to be deferred. /// </summary> /// <remarks> /// This special case is used to resolve circular references during the construction of /// object graphs. The object should not be used until its properties have been initialized. /// </remarks> /// <param name="class">The ActionScript class</param> /// <returns>The uninitialized object</returns> /// <exception cref="ArgumentNullException">Thrown if the <paramref name="class"/> is null /// (hint: use <see cref="ASClass.UntypedDynamicClass" /></exception> /// <exception cref="ArgumentException">Thrown if the layout of the class is not /// <see cref="ASClassLayout.Normal" /> or <see cref="ASClassLayout.Dynamic" /></exception> public static ASObject CreateUninitializedInstance(ASClass @class) { return(new ASObject(@class, false)); }
public void ConstructorWithClassAndMemberValuesAndDynamicValues(ASClassLayout classLayout, string[] memberNames, int[] memberValues) { IASValue[] asMemberValues = WrapInts(memberValues); IDictionary<string, IASValue> dynamicProperties = new Dictionary<string, IASValue>(); ASClass @class = new ASClass("class", classLayout, memberNames); ASObject obj = new ASObject(@class, asMemberValues, dynamicProperties); Assert.AreSame(@class, obj.Class); Assert.AreSame(asMemberValues, obj.MemberValues); Assert.AreSame(dynamicProperties, obj.DynamicProperties); }
public void EqualsWithSelfIsTrue() { ASClass class1 = new ASClass("abc", ASClassLayout.Dynamic, new string[] { "abc", "def" }); Assert.AreEqual(class1, class1); }
/// <summary> /// Creates an object with the specified class, member values and dynamic properties. /// </summary> /// <param name="class">The ActionScript class</param> /// <param name="memberValues">The member values of the object</param> /// <param name="dynamicProperties">The dynamic properties of the object</param> /// <exception cref="ArgumentNullException">Thrown if the <paramref name="class"/> is null /// (hint: use <see cref="ASClass.UntypedDynamicClass" /></exception> /// <exception cref="ArgumentNullException">Thrown when <paramref name="memberValues"/> or /// <paramref name="dynamicProperties"/> is null</exception> /// <exception cref="ArgumentException">Thrown if the layout of the class is not /// <see cref="ASClassLayout.Normal" /> or <see cref="ASClassLayout.Dynamic" /></exception> /// <exception cref="ArgumentException">Thrown if the number of members defined by the class /// differs from the count of <paramref name="memberValues"/></exception> public ASObject(ASClass @class, IList<IASValue> memberValues, IDictionary<string, IASValue> dynamicProperties) { if (@class == null) throw new ArgumentNullException("class", "Class must not be null. Did you mean to use ASClass.UntypedDynamicClass?"); if (memberValues == null) throw new ArgumentNullException("memberValues"); if (dynamicProperties == null) throw new ArgumentNullException("properties"); if (@class.Layout != ASClassLayout.Normal && @class.Layout != ASClassLayout.Dynamic) throw new ArgumentException("The class layout must be Normal or Dynamic.", "class"); if (@class.MemberNames.Count != memberValues.Count) throw new ArgumentException("The number of member values provided must equal the number of members defined by the class.", "class"); this.@class = @class; this.memberValues = memberValues; this.dynamicProperties = dynamicProperties; }
/// <summary> /// Creates an object with the specified class and no member values or dynamic properties initially set. /// </summary> /// <remarks> /// The object will have a fixed-length list of member values with the same length as the /// list of member names defined by the class. /// /// The object will have a read-only empty dynamic property dictionary if its /// class layout is <see cref="ASClassLayout.Normal" />, otherwise it will have /// a read-write dictionary. /// </remarks> /// <param name="class">The ActionScript class</param> /// <exception cref="ArgumentNullException">Thrown if the <paramref name="class"/> is null /// (hint: use <see cref="ASClass.UntypedDynamicClass" /></exception> /// <exception cref="ArgumentException">Thrown if the layout of the class is not /// <see cref="ASClassLayout.Normal" /> or <see cref="ASClassLayout.Dynamic" /></exception> public ASObject(ASClass @class) { if (@class == null) throw new ArgumentNullException("class", "Class must not be null. Did you mean to use ASClass.UntypedDynamicClass?"); if (@class.Layout != ASClassLayout.Normal && @class.Layout != ASClassLayout.Dynamic) throw new ArgumentException("The class layout must be Normal or Dynamic.", "class"); this.@class = @class; this.memberValues = @class.MemberNames.Count != 0 ? new IASValue[@class.MemberNames.Count] : EmptyArray<IASValue>.Instance; this.dynamicProperties = @class.Layout == ASClassLayout.Dynamic ? new Dictionary<string, IASValue>() : EmptyDictionary<string, IASValue>.Instance; }
/// <summary> /// Creates an instance whose initialization is to be deferred. /// </summary> /// <remarks> /// This special case is used to resolve circular references during the construction of /// object graphs. The object should not be used until its properties have been initialized. /// </remarks> /// <param name="class">The ActionScript class</param> /// <exception cref="ArgumentNullException">Thrown when <paramref name="class"/> is null</exception> /// <exception cref="ArgumentException">Thrown when the class layout of <paramref name="class"/> is /// not <see cref="ASClassLayout.Externalizable" /></exception> /// <returns>The uninitialized object</returns> public static ASExternalizableObject CreateUninitializedInstance(ASClass @class) { return(new ASExternalizableObject(@class)); }
/// <summary> /// Creates an instance whose initialization is to be deferred. /// </summary> /// <remarks> /// This special case is used to resolve circular references during the construction of /// object graphs. The object should not be used until its properties have been initialized. /// </remarks> /// <param name="class">The ActionScript class</param> /// <exception cref="ArgumentNullException">Thrown when <paramref name="class"/> is null</exception> /// <exception cref="ArgumentException">Thrown when the class layout of <paramref name="class"/> is /// not <see cref="ASClassLayout.Externalizable" /></exception> /// <returns>The uninitialized object</returns> public static ASExternalizableObject CreateUninitializedInstance(ASClass @class) { return new ASExternalizableObject(@class); }
public void EqualsWithNonClassIsFalse() { ASClass class1 = new ASClass("abc", ASClassLayout.Dynamic, new string[] { "abc", "def" }); Assert.AreNotEqual(class1, "abc"); }
/// <summary> /// Creates an untyped dynamic object with no member values or dynamic properties initially set. /// </summary> /// <remarks> /// The object will have an empty read-only list of member values and a read-write /// dictionary of dynamic properties. /// </remarks> public ASObject() { this.@class = ASClass.UntypedDynamicClass; this.memberValues = EmptyArray <IASValue> .Instance; this.dynamicProperties = new Dictionary <string, IASValue>(); }