Implementing a Property Searcher
I don't have a C# compiler at hand and cannot test the following.

It looks like the Search() always returns the sum of results of these 3 things:


delegate the call to any property that's ISearchable.
search the value of some properties
do not search the value of some other properties


The method will likely always consist of a list of these types of code blocks:


the delegate type   

foreach (var searchResult in this.PROPERTY_THAT_IS_ISEARCHABLE.Search(searchString))
{
    yield return searchResult;
}

for the direct search

yield return this.Search(searchString, this.GetType().GetProperty(nameof(this.PROPERTY_THATS_NOT_ISEARCHABLE)));

no code for excluded properties


This smells like copy&amp;paste. But you are already doing reflection, so why not use it to your advantage? 

I think you can create a generic Search() method, then slap that onto everything that implements ISearchable via extension, getting you rid of explicitely implementing the method in those classes. Here's how:


You should be able to filter out all properties that implement ISearchable and delegate the method call to them.
For non-ISearchable properties that should be searched, you should decide if they are the minority1. If so, define an attribute to opt-in a property. You'd then ignore all non-ISearchable by default and only search the values of those that are explicitly opted-in with the attribute.
For non-ISearchable properties that should not be searched, do pretty much the opposite of (2.). If they are the minority, create and add to them an attribute explicitly to opt-out of the default which would be to search all non-ISearchable properties.


1 The minority thing is only to reduce future work, minimizing the amount of attributes that you have to add. Attributes are optional, so you have to define some default behaviour anyway.

Let's say the default behaviour is to search all properties and opt-out via attribute. Here's how your classes could look like:

public class Book : ISearchable
{
    public DescriptionInfo DescriptionInfo { get; set; }
    public string Title { get; set; }
}


As you can see in the Book class: ISearchable is more or less a marker interface.

public class DescriptionInfo : ISearchable
{
    public string Description { get; set; }

    [IgnoreThisDuringSearch]
    public string ShortDescription { get; private set; }

    public DescriptionInfo(string description)
    {
        if (!string.IsNullOrEmpty(description))
        {
            this.Description = this.ShortDescription = description;
        }
    }
}


The generic extension method would perform the following two steps then:


delegate to every property that it can be delegated to
search every property that got opt-in via attribute or search every property except those opt-out via attribute




Some additional thoughts:

The attribute makes the search independent from the actual names of the properties. If you change Title to Totle in the Book class, you current code breaks. The suggested solution is solely based on reflection and existance (lack of) an attribute, which should always work, given a sensible default behaviour.

If you wish to perform the searching/delegating in a special order, you could do that, too. For example via a property of another attribute. See [DataMember(Order = n)] for example.