I want to search some or all public properties of a class and for this requirement I have implemented a Property Searcher
.
The Input for a Search
is always a string
. The Output contains the SearchString
, the SearchContent
in which the SearchString
is contained and the searched Property
.The Output is wrapped in a SearchResult
object.
This is what i have implemented:
SearchResult.cs
public class SearchResult
{
public PropertyInfo Property { get; private set; }
public string SearchString { get; private set; }
public string SearchContent { get; private set; }
public ISearchable Item { get; private set; }
public SearchResult(ISearchable item,
PropertyInfo property,
string searchString)
{
this.Property = property;
this.SearchString = searchString;
this.Item = item;
this.SearchContent = property.GetValue(item).ToString();
}
}
ISearchable.cs
public interface ISearchable
{
IEnumerable<SearchResult> Search(string searchString);
}
Extension Methods for easier usage:
Extension.cs
public static class Extension
{
public static SearchResult Search(this ISearchable source, string searchString, PropertyInfo info)
{
if (info.GetValue(source).ToString().Contains(searchString, StringComparison.OrdinalIgnoreCase))
{
return new SearchResult(source, info, searchString);
}
return null;
}
public static IEnumerable<SearchResult> Search(this IEnumerable<ISearchable> source, string searchString)
{
return source.SelectMany(searchable => searchable.Search(searchString)).Where(x => x != null);
}
public static bool Contains(this string source, string toCheck, StringComparison comp)
{
return source.IndexOf(toCheck, comp) >= 0;
}
}
I also want to show you the example and test code for e.g. searching in the property of a Book
with a Description
(the code is simplified and more complex in the original project).
Book.cs
public class Book : ISearchable
{
public DescriptionInfo DescriptionInfo { get; set; }
public string Title { get; set; }
public IEnumerable<SearchResult> Search(string searchString)
{
yield return this.Search(searchString, this.GetType().GetProperty(nameof(this.Title)));
foreach (var searchResult in this.DescriptionInfo.Search(searchString))
{
yield return searchResult;
}
}
}
Description.cs
public class DescriptionInfo : ISearchable
{
public string Description { get; set; }
public string ShortDescription { get; private set; }
public DescriptionInfo(string description)
{
if (!string.IsNullOrEmpty(description))
{
this.Description = this.ShortDescription = description;
}
}
public IEnumerable<SearchResult> Search(string searchString)
{
yield return this.Search(searchString, this.GetType().GetProperty(nameof(this.Description)));
}
}
Program.cs
internal class Program
{
private static void Main(string[] args)
{
var one = new Book
{
Title = "This Test Title is Amazing",
DescriptionInfo = new DescriptionInfo("This i a nice Test Book Description")
};
var two = new Book
{
Title = "This second Test Title is Amazing",
DescriptionInfo = new DescriptionInfo("This i a nice Book Description")
};
var three = new Book {Title = "Boring Title", DescriptionInfo = new DescriptionInfo("No Description")};
var list = new List<Book>(new[] {one, two, three});
var results = list.Search("Test").ToList();
}
}
In results
are three SearchResult
objects. The string
"Test" was found two times in a Title
Property and one time in the Description
Property of the Description
class.
I do not know if this is the best solution to solve the problem. If you have a better one in mind please let me know.