Example #1
0
        /// <summary>
        /// Initializes an ActionScript source mapping descriptor.
        /// </summary>
        /// <param name="sourceKind">The source value kind</param>
        /// <param name="sourceClassAlias">The source class alias, may be empty but never null</param>
        /// <param name="targetNativeType">The type of native objects to which values are mapped, never null</param>
        /// <param name="sourceContentFlags">Flags that describe abstract properties of the contents of the source value</param>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="targetNativeType"/> or
        /// <see cref="sourceClassAlias" /> is null</exception>
        public ASSourceMappingDescriptor(ASTypeKind sourceKind, string sourceClassAlias, ASValueContentFlags sourceContentFlags,
                                         Type targetNativeType)
        {
            if (targetNativeType == null)
            {
                throw new ArgumentNullException("sourceNativeType");
            }
            if (sourceClassAlias == null)
            {
                throw new ArgumentNullException("sourceClassAlias");
            }

            this.sourceKind         = sourceKind;
            this.sourceClassAlias   = sourceClassAlias;
            this.sourceContentFlags = sourceContentFlags;
            this.targetNativeType   = targetNativeType;
        }
        /// <summary>
        /// Gets the default native type to use for mapping ActionScript values with certain properties.
        /// </summary>
        /// <remarks>
        /// The default native type can be used when insufficient type information is available to
        /// perform a mapping unambiguously.
        /// </remarks>
        /// <param name="kind">The value's kind</param>
        /// <param name="classAlias">The value's class alias or an empty string if none</param>
        /// <param name="contentFlags">The value's content flags</param>
        /// <returns>The default native type</returns>
        public Type GetDefaultNativeType(ASTypeKind kind, string classAlias, ASValueContentFlags contentFlags)
        {
            switch (kind)
            {
                case ASTypeKind.Array:
                    if ((contentFlags & ASValueContentFlags.HasDynamicProperties) == 0)
                        return typeof(object[]);
                    if ((contentFlags & ASValueContentFlags.HasIndexedValues) == 0)
                        return typeof(Dictionary<string, object>);
                    return typeof(MixedArray<object>);

                case ASTypeKind.Boolean:
                    return typeof(bool);

                case ASTypeKind.ByteArray:
                    return typeof(byte[]);

                case ASTypeKind.Date:
                    return typeof(DateTime);

                case ASTypeKind.Int29:
                    return typeof(int);

                case ASTypeKind.Null:
                    return typeof(object);

                case ASTypeKind.Number:
                    return typeof(double);

                case ASTypeKind.Object:
                    if (classAlias.Length != 0)
                    {
                        ActionScriptClassMapping classMapping = GetClassMappingByAlias(classAlias);
                        if (classMapping != null)
                            return classMapping.NativeType;
                    }

                    // Map untyped and unknown objects to dictionaries.
                    return typeof(Dictionary<string, object>);

                case ASTypeKind.String:
                    return typeof(string);

                case ASTypeKind.Undefined:
                    return typeof(ASUndefined);

                case ASTypeKind.Unsupported:
                    return typeof(ASUnsupported);

                case ASTypeKind.Xml:
                    return typeof(XmlDocument);

                default:
                    throw new ActionScriptException(String.Format(CultureInfo.CurrentCulture,
                        "Unsupported type kind '{0}'.", kind));
            }
        }
Example #3
0
        private object UncachedToNative(IASValue asValue, Type nativeType)
        {
            ASTypeKind          kind         = asValue.Kind;
            ASClass             asClass      = asValue.Class;
            string              classAlias   = asClass != null ? asClass.ClassAlias : "";
            ASValueContentFlags contentFlags = asValue.ContentFlags;

            Type defaultNativeType = mappingTable.GetDefaultNativeType(kind, classAlias, contentFlags);

            // If the requested native type is not as precise as the default native type,
            // then use the default native type instead.  This rule is intended to avoid
            // the ambiguities that occur if we try to map to type "object" or some other
            // type that is too general.
            if (nativeType == null || nativeType.IsAssignableFrom(defaultNativeType))
            {
                nativeType = defaultNativeType;
            }

            // Quick short circuit if the desired type is a subtype of IASValue so mapping won't help.
            if (!typeof(IASValue).IsAssignableFrom(nativeType))
            {
                // Note: This will handle uninitialized values by returning null if no trivial
                //       conversion is possible without complete initialization.
                object value = asValue.GetNativeValue(nativeType);
                if (value != null)
                {
                    return(value);
                }

                // If the value isn't initialized then give up because we might have to do mapping.
                if (!asValue.IsInitialized)
                {
                    throw new ActionScriptException(String.Format(CultureInfo.CurrentCulture,
                                                                  "The ActionScript value cannot be mapped to type '{0}' because it is not completely initialized.",
                                                                  nativeType != null ? nativeType.FullName : "<default>"));
                }

                // Use mappers.
                // FIXME: This won't work if mapping ends up being recursive!
                ASSourceMappingDescriptor descriptor = new ASSourceMappingDescriptor(kind, classAlias, contentFlags, nativeType);
                IASSourceMapper           mapper     = mappingTable.GetASSourceMapper(descriptor);
                if (mapper != null)
                {
                    return(mapper.ToNative(this, asValue, nativeType));
                }
            }

            // Apply default handling for null references.
            if (asValue == ASNull.Value && !nativeType.IsValueType)
            {
                return(null);
            }

            // As a last resort, if we can assign the AS value to the original type requested then
            // do so.  We generally prefer mappings over returning IASValue instances, but if there
            // is no other choice...
            if (nativeType.IsInstanceOfType(asValue))
            {
                return(asValue);
            }

            // Give up!
            throw new ActionScriptException(String.Format(CultureInfo.CurrentCulture,
                                                          "Cannot find a suitable mapper for mapping an ActionScript value of kind '{0}' with class alias '{1}' to an instance of type '{2}'.",
                                                          asValue.Kind, classAlias, nativeType != null ? nativeType.FullName : "<default>"));
        }
Example #4
0
        /// <summary>
        /// Gets the default native type to use for mapping ActionScript values with certain properties.
        /// </summary>
        /// <remarks>
        /// The default native type can be used when insufficient type information is available to
        /// perform a mapping unambiguously.
        /// </remarks>
        /// <param name="kind">The value's kind</param>
        /// <param name="classAlias">The value's class alias or an empty string if none</param>
        /// <param name="contentFlags">The value's content flags</param>
        /// <returns>The default native type</returns>
        public Type GetDefaultNativeType(ASTypeKind kind, string classAlias, ASValueContentFlags contentFlags)
        {
            switch (kind)
            {
            case ASTypeKind.Array:
                if ((contentFlags & ASValueContentFlags.HasDynamicProperties) == 0)
                {
                    return(typeof(object[]));
                }
                if ((contentFlags & ASValueContentFlags.HasIndexedValues) == 0)
                {
                    return(typeof(Dictionary <string, object>));
                }
                return(typeof(MixedArray <object>));

            case ASTypeKind.Boolean:
                return(typeof(bool));

            case ASTypeKind.ByteArray:
                return(typeof(byte[]));

            case ASTypeKind.Date:
                return(typeof(DateTime));

            case ASTypeKind.Int29:
                return(typeof(int));

            case ASTypeKind.Null:
                return(typeof(object));

            case ASTypeKind.Number:
                return(typeof(double));

            case ASTypeKind.Object:
                if (classAlias.Length != 0)
                {
                    ActionScriptClassMapping classMapping = GetClassMappingByAlias(classAlias);
                    if (classMapping != null)
                    {
                        return(classMapping.NativeType);
                    }
                }

                // Map untyped and unknown objects to dictionaries.
                return(typeof(Dictionary <string, object>));

            case ASTypeKind.String:
                return(typeof(string));

            case ASTypeKind.Undefined:
                return(typeof(ASUndefined));

            case ASTypeKind.Unsupported:
                return(typeof(ASUnsupported));

            case ASTypeKind.Xml:
                return(typeof(XmlDocument));

            default:
                throw new ActionScriptException(String.Format(CultureInfo.CurrentCulture,
                                                              "Unsupported type kind '{0}'.", kind));
            }
        }