/// <summary>
        /// Ahead of time compilations that are available. The type maps to the
        /// object type the generated converter will serialize/deserialize, and
        /// the string is the text content for a converter that will do the
        /// serialization.
        /// <para/>
        /// The generated serializer is completely independent and you don't need
        /// to do anything. Simply add the file to your project and it'll get
        /// used instead of the reflection based one.
        /// </summary>
        public static string RunAotCompilationForType(fsConfig config, Type type)
        {
            fsMetaType metatype = fsMetaType.Get(config, type);

            metatype.EmitAotData(/*throwException:*/ true);
            return(GenerateDirectConverterForTypeInCSharp(type, metatype.Properties, metatype.IsDefaultConstructorPublic));
        }
        public static fsMetaType Get(fsConfig config, Type type)
        {
            Dictionary <Type, fsMetaType> metaTypes;

            lock (typeof(fsMetaType)) {
                if (_configMetaTypes.TryGetValue(config, out metaTypes) == false)
                {
                    metaTypes = _configMetaTypes[config] = new Dictionary <Type, fsMetaType>();
                }
            }

            fsMetaType metaType;

            if (metaTypes.TryGetValue(type, out metaType) == false)
            {
                metaType        = new fsMetaType(config, type);
                metaTypes[type] = metaType;
            }

            return(metaType);
        }
        /// <summary>
        /// Returns true if the given aotModel can be used. Returns false if it needs to
        /// be recompiled.
        /// </summary>
        public static bool IsAotModelUpToDate(fsMetaType currentModel, fsIAotConverter aotModel)
        {
            if (currentModel.IsDefaultConstructorPublic != aotModel.VersionInfo.IsConstructorPublic)
            {
                return(false);
            }

            if (currentModel.Properties.Length != aotModel.VersionInfo.Members.Length)
            {
                return(false);
            }

            foreach (fsMetaProperty property in currentModel.Properties)
            {
                if (HasMember(aotModel.VersionInfo, new fsAotVersionInfo.Member(property)) == false)
                {
                    return(false);
                }
            }

            return(true);
        }