/// <summary>
        /// Initialize the structure for an object
        /// </summary>
        /// <param name="localName">Name of the class</param>
        /// <param name="fullName">The fully qualified name of this object. Used as the object's key in the cache</param>
        /// <param name="properties">A readonly list of the properties and fields in this object</param>
        /// <param name="customAttributes">Custom attributes annotated at the class level</param>
        public ClassInfo(string localName, string fullName,
                         IReadOnlyList <PropertyInfo> properties, IReadOnlyList <FieldInfo> fields,
                         IEnumerable <Attribute> customAttributes)
        {
            ClassName          = localName;
            FullyQualifiedName = fullName;
            Properties         = properties;
            Fields             = fields;

            if ((properties != null) && (properties.Count > 0))
            {
                foreach (PropertyInfo p in properties)
                {
                    QHT.Add(p.MemberName, 'P');
                }
            }

            if ((fields != null) && (fields.Count > 0))
            {
                foreach (FieldInfo p in fields)
                {
                    QHT.Add(p.MemberName, 'F');
                }
            }

            CustomAttributes = customAttributes;
        }
        /// <summary>
        /// Writes a value to the class
        /// </summary>
        /// <typeparam name="ClassT">Type of class</typeparam>
        /// <param name="obj">Instance of class</param>
        /// <param name="propertyOrFieldName">Name of property or field</param>
        /// <param name="value">Value to write</param>
        public void Write <ClassT>(ClassT obj, string propertyOrFieldName, object value)
            where ClassT : class
        {
            if (QHT.TryGetValue(propertyOrFieldName, out char type))
            {
                switch (type)
                {
                case 'P':
                    foreach (PropertyInfo p in Properties)
                    {
                        if (p.MemberName == propertyOrFieldName)
                        {
                            p.Write(obj, value);
                            return;
                        }
                    }
                    break;

                case 'F':
                    foreach (FieldInfo f in Fields)
                    {
                        if (f.MemberName == propertyOrFieldName)
                        {
                            f.Write(obj, value);
                            return;
                        }
                    }
                    break;
                }
            }

            throw new InvalidOperationException($"'{propertyOrFieldName}' is not a loaded property or field in the class '{ClassName}'.");
        }