Beispiel #1
0
        /// <summary>
        /// Registers a class mapping.
        /// </summary>
        /// <param name="classMapping">The class mapping data</param>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="classMapping"/> is null</exception>
        /// <exception cref="ActionScriptException">Thrown if the mapped native type
        /// or its ActionScript alias have already been registered with different mappings</exception>
        public void RegisterClassMapping(ActionScriptClassMapping classMapping)
        {
            if (classMapping == null)
            {
                throw new ArgumentNullException("classMapping");
            }

            lock (syncRoot)
            {
                if (classMappingsByType.ContainsKey(classMapping.NativeType))
                {
                    throw new ActionScriptException(String.Format(CultureInfo.CurrentCulture,
                                                                  "Cannot register class mapping because there is already a mapper registered (or cached) for native type '{0}'.",
                                                                  classMapping.NativeType));
                }

                if (classMappingsByAlias.ContainsKey(classMapping.ASClass.ClassAlias))
                {
                    throw new ActionScriptException(String.Format(CultureInfo.CurrentCulture,
                                                                  "Cannot register class mapping because there is already a mapper registered (or cached) for class alias '{0}'.",
                                                                  classMapping.ASClass.ClassAlias));
                }

                // Now having validated the changes, apply them.
                classMappingsByType.Add(classMapping.NativeType, classMapping);

                string classAlias = classMapping.ASClass.ClassAlias;
                if (classAlias.Length != 0)
                {
                    classMappingsByAlias.Add(classAlias, classMapping);
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// Registers a type for serialization with the specified class alias.
        /// </summary>
        /// <remarks>
        /// This method is equivalent to calling <see cref="ActionScriptMappingReflector.CreateClassMapping" />
        /// followed by <see cref="RegisterClassMapping" />.
        /// It serves a similar purpose to the "flex.net.registerClassAlias" method on the client side.
        /// </remarks>
        /// <param name="nativeType">The native type</param>
        /// <param name="classAliasOverride">The ActionScript class alias</param>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="nativeType"/> is null</exception>
        /// <exception cref="ActionScriptException">Thrown if the mapped native type
        /// or the class alias have already been registered with different mappings</exception>
        /// <exception cref="ActionScriptException">Thrown when an error occurs generating the class mapping</exception>
        public void RegisterType(Type nativeType, string classAliasOverride)
        {
            if (nativeType == null)
            {
                throw new ArgumentNullException("nativeType");
            }

            ActionScriptClassMapping classMapping = ActionScriptMappingReflector.CreateClassMapping(nativeType, classAliasOverride);

            RegisterClassMapping(classMapping);
        }
Beispiel #3
0
        /// <inheritdoc />
        public override IASTargetMapper GetASTargetMapper(ASTargetMappingDescriptor descriptor)
        {
            ActionScriptClassMapping classMapping = mappingTable.GetClassMappingByType(descriptor.SourceNativeType);

            if (classMapping != null)
            {
                return(new ObjectMapper(classMapping));
            }

            return(null);
        }
Beispiel #4
0
        /// <inheritdoc />
        public override IASSourceMapper GetASSourceMapper(ASSourceMappingDescriptor descriptor)
        {
            if (descriptor.SourceKind == ASTypeKind.Object)
            {
                ActionScriptClassMapping classMapping = mappingTable.GetClassMappingByAlias(descriptor.SourceClassAlias);
                if (classMapping != null && descriptor.TargetNativeType.IsAssignableFrom(classMapping.NativeType))
                {
                    return(new ObjectMapper(classMapping));
                }
            }

            return(null);
        }
Beispiel #5
0
        /// <summary>
        /// Generates class mappings for all public types in the specified assembly
        /// that are decorated with the <see cref="ActionScriptClassAttribute" />.
        /// </summary>
        /// <param name="assembly">The assembly to search for serializable types</param>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="assembly"/> is null</exception>
        /// <returns>The enumeration of class mappings</returns>
        public static IEnumerable <ActionScriptClassMapping> GetClassMappingsForTypesInAssembly(Assembly assembly)
        {
            if (assembly == null)
            {
                throw new ArgumentNullException("assembly");
            }

            foreach (Type type in assembly.GetExportedTypes())
            {
                ActionScriptClassAttribute classAttribute = GetActionScriptClassAttribute(type);
                if (classAttribute != null)
                {
                    ActionScriptClassMapping classMapping = InternalCreateDefaultClassMapping(type, null, classAttribute);
                    yield return(classMapping);
                }
            }
        }
        private static ActionScriptClassMapping InternalCreateDefaultClassMapping(Type nativeType, string classAliasOverride,
            ActionScriptClassAttribute classAttribute)
        {
            // Determine the class alias.
            string classAlias;

            if (classAliasOverride != null)
                classAlias = classAliasOverride;
            else if (classAttribute != null)
                classAlias = classAttribute.ClassAlias;
            else
                classAlias = "";

            // Determine the class layout.
            ASClassLayout classLayout = ASClassLayout.Normal;

            if (typeof(IDynamic).IsAssignableFrom(nativeType))
            {
                classLayout = ASClassLayout.Dynamic;
            }

            if (typeof(IExternalizable).IsAssignableFrom(nativeType))
            {
                if (classAlias.Length == 0)
                    throw new ActionScriptException(String.Format(CultureInfo.CurrentCulture,
                        "Type '{0}' implements IExternalizable but does not have a non-empty class alias name which is required by the externalizable serialization protocol.",
                        nativeType.FullName));

                if (classLayout == ASClassLayout.Dynamic)
                    throw new ActionScriptException(String.Format(CultureInfo.CurrentCulture,
                        "Type '{0}' implements IExternalizable as well as IDynamic which is not supported by the externalizable serialization protocol.",
                        nativeType.FullName));

                classLayout = ASClassLayout.Externalizable;
            }

            // Populate the list of property mappings.
            List<ActionScriptPropertyMapping> propertyMappings = new List<ActionScriptPropertyMapping>();
            List<string> memberNames = new List<string>();

            foreach (PropertyInfo property in nativeType.GetProperties(BindingFlags.Instance | BindingFlags.Public))
            {
                AddPropertyMappingIfNeeded(property, propertyMappings, memberNames, ref classLayout);
            }

            foreach (FieldInfo field in nativeType.GetFields(BindingFlags.Instance | BindingFlags.Public))
            {
                AddPropertyMappingIfNeeded(field, propertyMappings, memberNames, ref classLayout);
            }

            // Finish up.
            // Convert the lists to arrays to reduce the memory footprint.
            string[] memberNamesArray = memberNames.Count == 0 ? EmptyArray<string>.Instance : memberNames.ToArray();
            ActionScriptPropertyMapping[] propertyMappingsArray = propertyMappings.Count == 0 ?
                EmptyArray<ActionScriptPropertyMapping>.Instance : propertyMappings.ToArray();

            ASClass classDefinition = ASClassCache.GetClass(classAlias, classLayout, memberNamesArray);
            ActionScriptClassMapping classMapping = new ActionScriptClassMapping(nativeType, classDefinition, propertyMappingsArray);

            return classMapping;
        }
        /// <summary>
        /// Registers a class mapping.
        /// </summary>
        /// <param name="classMapping">The class mapping data</param>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="classMapping"/> is null</exception>
        /// <exception cref="ActionScriptException">Thrown if the mapped native type
        /// or its ActionScript alias have already been registered with different mappings</exception>
        public void RegisterClassMapping(ActionScriptClassMapping classMapping)
        {
            if (classMapping == null)
                throw new ArgumentNullException("classMapping");

            lock (syncRoot)
            {
                if (classMappingsByType.ContainsKey(classMapping.NativeType))
                    throw new ActionScriptException(String.Format(CultureInfo.CurrentCulture,
                        "Cannot register class mapping because there is already a mapper registered (or cached) for native type '{0}'.",
                        classMapping.NativeType));

                if (classMappingsByAlias.ContainsKey(classMapping.ASClass.ClassAlias))
                    throw new ActionScriptException(String.Format(CultureInfo.CurrentCulture,
                        "Cannot register class mapping because there is already a mapper registered (or cached) for class alias '{0}'.",
                        classMapping.ASClass.ClassAlias));

                // Now having validated the changes, apply them.
                classMappingsByType.Add(classMapping.NativeType, classMapping);

                string classAlias = classMapping.ASClass.ClassAlias;
                if (classAlias.Length != 0)
                    classMappingsByAlias.Add(classAlias, classMapping);
            }
        }
Beispiel #8
0
        private static ActionScriptClassMapping InternalCreateDefaultClassMapping(Type nativeType, string classAliasOverride,
                                                                                  ActionScriptClassAttribute classAttribute)
        {
            // Determine the class alias.
            string classAlias;

            if (classAliasOverride != null)
            {
                classAlias = classAliasOverride;
            }
            else if (classAttribute != null)
            {
                classAlias = classAttribute.ClassAlias;
            }
            else
            {
                classAlias = "";
            }

            // Determine the class layout.
            ASClassLayout classLayout = ASClassLayout.Normal;

            if (typeof(IDynamic).IsAssignableFrom(nativeType))
            {
                classLayout = ASClassLayout.Dynamic;
            }

            if (typeof(IExternalizable).IsAssignableFrom(nativeType))
            {
                if (classAlias.Length == 0)
                {
                    throw new ActionScriptException(String.Format(CultureInfo.CurrentCulture,
                                                                  "Type '{0}' implements IExternalizable but does not have a non-empty class alias name which is required by the externalizable serialization protocol.",
                                                                  nativeType.FullName));
                }

                if (classLayout == ASClassLayout.Dynamic)
                {
                    throw new ActionScriptException(String.Format(CultureInfo.CurrentCulture,
                                                                  "Type '{0}' implements IExternalizable as well as IDynamic which is not supported by the externalizable serialization protocol.",
                                                                  nativeType.FullName));
                }

                classLayout = ASClassLayout.Externalizable;
            }

            // Populate the list of property mappings.
            List <ActionScriptPropertyMapping> propertyMappings = new List <ActionScriptPropertyMapping>();
            List <string> memberNames = new List <string>();

            foreach (PropertyInfo property in nativeType.GetProperties(BindingFlags.Instance | BindingFlags.Public))
            {
                AddPropertyMappingIfNeeded(property, propertyMappings, memberNames, ref classLayout);
            }

            foreach (FieldInfo field in nativeType.GetFields(BindingFlags.Instance | BindingFlags.Public))
            {
                AddPropertyMappingIfNeeded(field, propertyMappings, memberNames, ref classLayout);
            }

            // Finish up.
            // Convert the lists to arrays to reduce the memory footprint.
            string[] memberNamesArray = memberNames.Count == 0 ? EmptyArray <string> .Instance : memberNames.ToArray();
            ActionScriptPropertyMapping[] propertyMappingsArray = propertyMappings.Count == 0 ?
                                                                  EmptyArray <ActionScriptPropertyMapping> .Instance : propertyMappings.ToArray();

            ASClass classDefinition = ASClassCache.GetClass(classAlias, classLayout, memberNamesArray);
            ActionScriptClassMapping classMapping = new ActionScriptClassMapping(nativeType, classDefinition, propertyMappingsArray);

            return(classMapping);
        }
Beispiel #9
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));
            }
        }
Beispiel #10
0
            public ObjectMapper(ActionScriptClassMapping classMapping)
            {
                this.classMapping = classMapping;

                PopulateTables();
            }
            public ObjectMapper(ActionScriptClassMapping classMapping)
            {
                this.classMapping = classMapping;

                PopulateTables();
            }