private static void AddProperty(this IDictionary<string, object> parms, PropertyInfo p, object o, string prefix = "")
        {
            object value = p.GetValue(o);
            // filter out sentinals values for unitialized search fields
            if (value != null && !value.Equals(0) && !value.Equals(DateTime.MinValue))
            {
                // if the property is a string just add it
                if (value is string)
                    parms.Add(prefix + p.Name, value);

                // value types
                else if (value.GetType().GetTypeInfo().IsValueType)
                {             
                    // serialize dates in the correct format
                    if (value is DateTime)
                        parms.Add(prefix + p.Name, ((DateTime)value).ToString("yyyy-MM-dd"));
                    else
                        parms.Add(prefix + p.Name, value);
                }

                // the property is a list in which case search on the first item's value - committee_ids is an example
                else if (value is IList<string> && ((IList<string>)value).Count > 0)
                    parms.Add(prefix + p.Name, ((IList<string>)value)[0]);

                // the property is marked as searchable but is a sub ojbect - recurse adding 
                // this property name as a prefix (history.house_passage_result is an example)
                else
                    parms.AddProperties(value, p.Name + ".");
            }
        }
 public static void AddParameterInfo(this JObject obj, ParameterInfo parameterInfo)
 {
     if (parameterInfo.ParameterType.IsPrimitive
         || parameterInfo.ParameterType == typeof(string)
         || parameterInfo.ParameterType == typeof(Guid))
     {
         obj.Add(parameterInfo.Name, parameterInfo.ParameterType.Name);
     }
     else if (parameterInfo.ParameterType.IsNullable())
     {
         obj.Add(parameterInfo.Name, parameterInfo.ParameterType.GenericTypeArguments[0].Name);
     }
     else
     {
         obj.AddProperties(parameterInfo.ParameterType);
     }
 }
 /// <summary>
 /// Adds configuration values from a text file.
 /// </summary>
 /// <remarks>
 /// Each line in the file will be treated as a separate configuration value, with the format:
 /// <c>foo.bar = value</c>
 /// </remarks>
 /// <param name="builder">The <see cref="IConfigurationBuilder"/>.</param>
 /// <param name="filePath">The file path.</param>
 /// <param name="required">
 /// Determines whether the file can be skipped silently. If <paramref name="required"/> is <see langword="true"/>,
 /// and the file does not exist, a <see cref="System.IO.FileNotFoundException"/> will be thrown. If <paramref name="required"/>
 /// is <see langword="false"/>, the method will return silently.
 /// </param>
 /// <param name="root">
 /// An optional root name to apply to any configuration values.
 /// For example, if <paramref name="root"/> is <c>foo</c>, and the value <c>bar = baz</c>
 /// is discovered, the actual added value will be <c>foo.bar = baz</c>.
 /// </param>
 /// <param name="logger">The logger.</param>
 public static IConfigurationBuilder AddPropertiesFile(
     this IConfigurationBuilder builder,
     string filePath,
     bool optional = false,
     string root = null,
     ILogger logger = null)
 {
     var contents = FileOperations.Load(filePath, optional);
     return builder.AddProperties(contents, root);
 }