Beispiel #1
0
        /// <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;
        }
Beispiel #2
0
        /// <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>();
        }
Beispiel #5
0
        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());
        }
Beispiel #6
0
        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);
        }
Beispiel #7
0
        /// <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;
        }
Beispiel #8
0
        /// <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;
        }
Beispiel #11
0
        /// <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;
        }
Beispiel #12
0
        /// <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;
        }
Beispiel #14
0
        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);
        }
Beispiel #15
0
        /// <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;
        }
Beispiel #16
0
        /// <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;
        }
Beispiel #17
0
        /// <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;
            }
        }
Beispiel #18
0
        /// <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;
        }
Beispiel #19
0
        /// <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);
            }
        }
Beispiel #20
0
        /// <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());
        }
Beispiel #25
0
 /// <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);
 }
Beispiel #26
0
        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"]);
        }
Beispiel #27
0
 /// <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);
 }
Beispiel #28
0
        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);
        }
Beispiel #29
0
 /// <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("");
                }
            }
        }
Beispiel #31
0
        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);
        }
Beispiel #32
0
        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;
        }
Beispiel #34
0
 /// <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));
 }
Beispiel #35
0
        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);
        }
Beispiel #36
0
 public void EqualsWithSelfIsTrue()
 {
     ASClass class1 = new ASClass("abc", ASClassLayout.Dynamic, new string[] { "abc", "def" });
     Assert.AreEqual(class1, class1);
 }
Beispiel #37
0
        /// <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;
        }
Beispiel #38
0
        /// <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;
        }
Beispiel #39
0
 /// <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);
 }
Beispiel #41
0
 public void EqualsWithNonClassIsFalse()
 {
     ASClass class1 = new ASClass("abc", ASClassLayout.Dynamic, new string[] { "abc", "def" });
     Assert.AreNotEqual(class1, "abc");
 }
Beispiel #42
0
 /// <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>();
 }