I need to create a dynamic linq expression for a dynamic search.The basic search is working but it fails to work with collection. I am able to get the book\'s title and auth
Based on your description I'm not sure that you need Expression
. Creating an Expression
with a complex object model is quite difficult. Do you really need to create dynamic expression or you simply need to create a dynamic query? If the object model is fixed then you don't need Expression
.
I suggest first of all to clean your object model:
Books
class to Book
(this class represents a Book not a list of books)Page
to Pages
(this property returns a list of pages)Now you can write a dynamic where using just LINQ and one or more helper functions one for each property that you need to search. For example to search for Heading
you can write:
private static bool SearchByHeading(Book b, string heading)
{
if (string.IsNullOrEmpty(heading))
return true;
else
return b.Pages.Any(p => p.Heading == heading);
}
Here you can also see why your previous code didn't work. The expression to search for a given Heading
is book.Pages.Any(p => p.Heading == x)
and not book.Pages.Heading == x
.
In any case given one or more functions like this you can rewrite your code with something like:
using System.Collections.Generic;
using System.Linq;
namespace XMLStorageAndFilter
{
public class Book
{
public Book()
{
Pages = new List();
}
public string Title { get; set; }
public Author Author { get; set; }
public List Pages { get; set; }
}
public class Author
{
public string FirstName { get; set; }
}
public class Page
{
public string Heading { get; set; }
}
public class Program2
{
static void Main()
{
Page page = new Page();
page.Heading = "Heading1";
Book bok = new Book();
bok.Title = "Title1";
bok.Author = new Author() { FirstName = "FirstName1" };
bok.Pages.Add(page);
List testList = new List();
testList.Add(bok);
var searchResult = Search(testList,
title: "Title1",
author: "FirstName1",
heading: "Heading1");
}
private static IEnumerable Search(IEnumerable books, string author = null, string title = null, string heading = null)
{
return books
.Where((b) => SearchByAuthor(b, author))
.Where((b) => SearchByHeading(b, heading))
.Where((b) => SearchByTitle(b, title))
.ToList();
}
private static bool SearchByAuthor(Book b, string author)
{
if (string.IsNullOrEmpty(author))
return true;
else
return b.Author.FirstName == author;
}
private static bool SearchByTitle(Book b, string title)
{
if (string.IsNullOrEmpty(title))
return true;
else
return b.Title == title;
}
private static bool SearchByHeading(Book b, string heading)
{
if (string.IsNullOrEmpty(heading))
return true;
else
return b.Pages.Any(p => p.Heading == heading);
}
}
}
I have skipped search values when null or empty, just an example. This code has also the advantage that is verified at compile time.