internal AttributedProperty(PropertyInfo property, FirestorePropertyAttribute attribute)
            {
                _propertyInfo  = property;
                FirestoreName  = attribute.Name ?? property.Name;
                _sentinelValue = SentinelValue.FromPropertyAttributes(property);
                if (attribute.ConverterType != null)
                {
                    _converter = CustomConverter.ForConverterType(attribute.ConverterType, property.PropertyType);
                }

                // Note that the error messages in here don't use nameof, as we don't have an overload of CheckState accepting three
                // format arguments.
                // TODO: Put that in GAX and use nameof.
                string typeName = property.DeclaringType.FullName;

                GaxPreconditions.CheckState(property.GetIndexParameters().Length == 0,
                                            "{0}.{1} is an indexer, and should not be decorated with FirestorePropertyAttribute.",
                                            typeName, property.Name);

                // Annoyingly, we can't easily check whether the property is static - we have to check the individual methods.
                var getMethod = property.GetGetMethod(nonPublic: true);
                var setMethod = property.GetSetMethod(nonPublic: true);

                GaxPreconditions.CheckState(getMethod == null || !getMethod.IsStatic,
                                            "{0}.{1} is static, and should not be decorated with FirestorePropertyAttribute.",
                                            typeName, property.Name);
                GaxPreconditions.CheckState(setMethod == null || !setMethod.IsStatic,
                                            "{0}.{1} is static, and should not be decorated with FirestorePropertyAttribute.",
                                            typeName, property.Name);
            }
            internal AttributedProperty(PropertyInfo property, FirestorePropertyAttribute attribute)
            {
                _propertyInfo  = property;
                FirestoreName  = attribute.Name ?? property.Name;
                _sentinelValue = SentinelValue.FromPropertyAttributes(property);
                if (attribute.ConverterType != null)
                {
                    _converter = CustomConverter.ForConverterType(attribute.ConverterType, property.PropertyType);
                }

                string typeName = property.DeclaringType.FullName;

                GaxPreconditions.CheckState(property.GetIndexParameters().Length == 0,
                                            "{0}.{1} is an indexer, and should not be decorated with {2}.",
                                            typeName, property.Name, nameof(FirestorePropertyAttribute));

                // Annoyingly, we can't easily check whether the property is static - we have to check the individual methods.
                var getMethod = property.GetGetMethod(nonPublic: true);
                var setMethod = property.GetSetMethod(nonPublic: true);

                GaxPreconditions.CheckState(getMethod == null || !getMethod.IsStatic,
                                            "{0}.{1} is static, and should not be decorated with {2}.",
                                            typeName, property.Name, nameof(FirestorePropertyAttribute));
                GaxPreconditions.CheckState(setMethod == null || !setMethod.IsStatic,
                                            "{0}.{1} is static, and should not be decorated with {2}.",
                                            typeName, property.Name, nameof(FirestorePropertyAttribute));
            }
        /// <summary>
        /// Factory method to construct a converter for an attributed type.
        /// </summary>
        internal static IFirestoreInternalConverter ForType(BclType targetType)
        {
            var typeInfo  = targetType.GetTypeInfo();
            var attribute = typeInfo.GetCustomAttribute <FirestoreDataAttribute>(inherit: false);

            // This would be an internal library bug. We shouldn't be calling it in this case.
            GaxPreconditions.CheckState(attribute != null, "Type {0} is not decorated with {1}.", targetType.FullName, nameof(FirestoreDataAttribute));

            return(attribute.ConverterType == null
                ? new AttributedTypeConverter(targetType, attribute)
                : CustomConverter.ForConverterType(attribute.ConverterType, targetType));
        }