System.Linq.Enumerable+WhereSelectListIterator`2 error - linq

I am getting this error : System.Linq.Enumerable+WhereSelectListIterator2[ConsoleApplication1.Person,<>f_
_AnonymousType02[System.String,System.String]]
When I try to do this in a console application :
public class Person
{
public int ID;
public int IDRole;
public string FirstName;
public string LastName;
}
class Program
{
static void Main(string[] args)
{
List<Person> people = new List<Person> {
new Person() {ID = 1, IDRole = 1, LastName= "Anderson",
FirstName = "Brad"},
new Person() {ID = 2, IDRole = 2, LastName= "Gray",
FirstName = "Tom"}
};
var query = from p in people
where p.ID == 1
select new { p.FirstName, p.LastName };
Console.Write( query);
Console.ReadLine();
}}

You need to iterate the query
foreach(var q in query)
{
Console.Write( string.Format("{0} {1}",new []{ q.FirstName ,q.LastName }));
}
Console.ReadLine();

Related

Thymeleaf : Call Java function in JavaScript Click listener

So I have this controller class with some getters and setters and a function:
#Controller
public class Hotels{
public Hotels(String name) {
this.name = name;
}
public Hotels(String name, String price, String longitude, String latitude, String URL, String photoURL) {
this.name = name;
this.price = price;
this.longitude = longitude;
this.latitude = latitude;
this.URL = URL;
PhotoURL = photoURL;
}
public Hotels() {
}
public List<Hotels> returnHotels(String city) throws IOException, InterruptedException {
double[] lnglat = new double[2];
MapController controller = new MapController();
for (int i = 0; i <controller.coolLocations().size(); i++) {
if(controller.coolLocations().get(i).getDescription().equals(city)){
lnglat = controller.coolLocations().get(i).getLnglat();
}
}
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://booking-com.p.rapidapi.com/v1/hotels/search-by-coordinates?order_by=popularity&adults_number=2&units=metric&room_number=1&checkout_date=2022-11-15&filter_by_currency=RON&locale=en-gb&checkin_date=2022-11-12&latitude="+lnglat[1]+"&longitude="+lnglat[0]))
.header("X-RapidAPI-Key", "myKey")
.header("X-RapidAPI-Host", "booking-com.p.rapidapi.com")
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
String[] datasplit = response.body().split("\"");
String url = "";
String hotel_name = "";
String latitude = "";
String longitude = "";
String gross_price= "";
String main_photo_url= "";
for (int i = 0; i < datasplit.length; i++) {
if (datasplit[i].equals("url")) url = datasplit[i+2];
if (datasplit[i].equals("hotel_name")) hotel_name = datasplit[i+2];
if (datasplit[i].equals("latitude")) latitude = datasplit[i+1].substring(1).replace(',',' ');
if (datasplit[i].equals("longitude")) longitude = datasplit[i+1].substring(1).replace(',',' ');
if ((datasplit[i].equals("gross_amount_hotel_currency") && datasplit[i+1].equals(":{") && datasplit[i+2].equals("value"))) gross_price = datasplit[i+3].substring(1).replace('}',' ').replace(',',' ');
if ((datasplit[i].equals("gross_amount_hotel_currency") && datasplit[i+1].equals(":{") && datasplit[i+2].equals("currency") && datasplit[i+3].equals(":") && datasplit[i+4].equals("EUR")&& datasplit[i+5].equals(",") && datasplit[i+6].equals("value"))) gross_price = datasplit[i+7].substring(1).replace('}',' ').replace(',',' ');
if (datasplit[i].equals("max_photo_url")) main_photo_url = datasplit[i+2];
if(datasplit[i].equals("max_1440_photo_url"))hotelsList.add(new Hotels(hotel_name, gross_price, longitude, latitude, url, main_photo_url));
}
hotelsList.forEach(System.out::println);
System.out.println(city);
return hotelsList;
}
}
And this is my get Mapping :
#GetMapping("/")
public String homePage(Model model) throws IOException, InterruptedException {
model.addAttribute("returnHotels", new Hotels());
return "home";
}
And a JavaScript on click listener :
marker.getElement().addEventListener('click', function () {
const city = location.description;
});
I want inside the JS click listener to call my returnHotels function with the const city as my parameter. Is it possible?
PS : I've deleted the class variables so the site let me post

How join List<Class> with IEnumerable<Class>?

I have the following classes.
public class Course
{
public string CourseNumber { get; set; }
public List<PriceGroup> PriceGroups { get; set; }
}
public class PriceGroup
{
public int Id { get; set; }
public string CourseNumber { get; set; }
}
I have a service that fetches data from the database. Courses is an IEnumerable<Course> and priceGroups is a IEnumerable<PriceGroup>. As you can see in the Course class, a course has a List<PriceGroup>. I need to somehow add each PriceGroup in the IEnumerable<PriceGroup> to the list in each course in the IEnumerable<Course> if they match on the variable CourseNumber. So I will end up with a correct Course containing the right List<PriceGroup>'s
public async Task<IEnumerable<Course>> GetAllAsync()
{
//courses is an IEnumerable<Course>
var courses = await _courseRepository.GetAllAsync();
//priceGroups is an IEnumerable<PriceGroup>
var priceGroups = await _coursePriceGroupRepository.GetAllAsync();
courses.GroupJoin(priceGroups, c => c.PriceGroups.Select(i => i.CourseNumber), pg => pg.CourseNumber, (c, pg) => new
{
});
return await courses;
}
To do this I've tried to do a GroupJoin but without success. I have not finished the attempt as I am completely stuck mentally. Perhaps I am trying to do something that is not possible with a GroupJoin. Does anyone know a way to achieve what I need?
So you want all (or some) Courses, each Course with all (or some of) its PriceGroups.
There is a straightforware one-to-many relation betweeen Courses and PriceGroups: Every Course has zero or more PriceGroups, every PriceGroup belongs to exactly one Course, namely the Course that foreign key CourseNumber refers to.
You are right, whenever you want items with their sub-items you use GroupJoin.
public async Task<IEnumerable<Course>> GetAllAsync()
{
IEnumerable<Course> courses = await _courseRepository.GetAllAsync();
IEnumerable<PriceGroup> priceGroups = await _coursePriceGroupRepository.GetAllAsync();
var queryCoursesWithPriceGroups = courses.GroupJoin( // GroupJoin Courses
priceGroups, // with PriceGroups
course => course.CourseNumber, // from every Course take primary key
priceGroup => priceGroup.CourseNumber, // from every PriceGroup take foreign key
(course, priceGroupsOfThisCourse) => new // from every Course with
{ // its priceGroups make one new
// Select the Course properties you plan to use:
Id = course.Id,
Name = course.Name,
StartDate = course.StartDate,
...
PriceGroups = priceGroupsOfThisCourse.Select(priceGroup => new
{
// Select only the PriceGroup properties that you plan to use
Id = priceGroup.Id,
Name = priceGroup.Name,
...
// not needed, you know the value:
// CourseId = priceGroup.CourseId
})
.ToList(),
});
// Note: this is a query. It is not executed yet!
return await queryCoursesWithPriceGroups.ToListAsync();
//Assuming courseNumber is unique in Courses table
return Courses.Select( c=> { c.PriceGroup=priceGroup.Where(p=>p.CourseNumber==c.CourseNumber).ToList(); return c; });
I did a practical example, obviously you should substitute the fake methods with repository ones:
class Program
{
static async void Main(string[] args)
{
var courses = GetAllAsync().Result;
}
private static async Task<IEnumerable<Course>> GetAllAsync()
{
//courses is an IEnumerable<Course>
var courses = await GetCoursesAsync();
//priceGroups is an IEnumerable<PriceGroup>
var priceGroups = await GetPriceGroups();
foreach (var course in courses)
{
foreach (var priceGroup in priceGroups.Where(x => x.CourseNumber == course.CourseNumber))
{
course.PriceGroups.Add(priceGroup);
}
}
return courses;
}
private static async Task<IEnumerable<Course>> GetCoursesAsync()
{
return await Task.FromResult<IEnumerable<Course>>(
new List<Course>() {
new Course{
CourseNumber = "PIZZA1",
PriceGroups = new List<PriceGroup>()
},
new Course{
CourseNumber = "PIZZA2",
PriceGroups = new List<PriceGroup>()
},
new Course{
CourseNumber = "PIZZA3",
PriceGroups = new List<PriceGroup>()
},
}
);
}
private static async Task<IEnumerable<PriceGroup>> GetPriceGroups()
{
return await Task.FromResult<IEnumerable<PriceGroup>>(
new List<PriceGroup>() {
new PriceGroup{
Id = 1,
CourseNumber = "PIZZA1"
},
new PriceGroup{
Id = 2,
CourseNumber = "PIZZA2"
},
new PriceGroup{
Id = 3,
CourseNumber = "PIZZA3"
}
}
);
}
}
public class Course
{
public string CourseNumber { get; set; }
public List<PriceGroup> PriceGroups { get; set; }
}
public class PriceGroup
{
public int Id { get; set; }
public string CourseNumber { get; set; }
}
You should avoid using IEnumerable when you return data from DB, you can incur in unexpected behaviours. I suggest you this approach:
class Program
{
static void Main(string[] args)
{
var courses = GetAllAsync().Result;
}
private static async Task<List<Course>> GetAllAsync()
{
var courses = await GetCoursesAsync();
var priceGroups = await GetPriceGroups();
courses.ForEach(x => { x.PriceGroups.AddRange(priceGroups.Where(y => y.CourseNumber == x.CourseNumber)); });
return courses;
}
private static async Task<List<Course>> GetCoursesAsync()
{
return await Task.FromResult(
new List<Course>() {
new Course{
CourseNumber = "PIZZA1",
PriceGroups = new List<PriceGroup>()
},
new Course{
CourseNumber = "PIZZA2",
PriceGroups = new List<PriceGroup>()
},
new Course{
CourseNumber = "PIZZA3",
PriceGroups = new List<PriceGroup>()
},
}
);
}
private static async Task<List<PriceGroup>> GetPriceGroups()
{
return await Task.FromResult(
new List<PriceGroup>() {
new PriceGroup{
Id = 1,
CourseNumber = "PIZZA1"
},
new PriceGroup{
Id = 2,
CourseNumber = "PIZZA2"
},
new PriceGroup{
Id = 3,
CourseNumber = "PIZZA3"
}
}
);
}
}
public class Course
{
public string CourseNumber { get; set; }
public List<PriceGroup> PriceGroups { get; set; }
}
public class PriceGroup
{
public int Id { get; set; }
public string CourseNumber { get; set; }
}
I made a version using GroupJoin too:
class Program
{
static void Main(string[] args)
{
var courses = GetAllAsync().Result;
}
private static async Task<List<Course>> GetAllAsync()
{
var courses = await GetCoursesAsync();
var priceGroups = await GetPriceGroups();
var groupedData = courses.GroupJoin(priceGroups,
course => course.CourseNumber,
priceGroup => priceGroup.CourseNumber,
(course, priceGroupsCollection) =>
new
{
CourseNumber = course.CourseNumber,
PriceGroups = priceGroupsCollection.ToList()
});
courses.ForEach(x => { x.PriceGroups = groupedData.FirstOrDefault(y => y.CourseNumber == x.CourseNumber)?.PriceGroups ?? new List<PriceGroup>(); });
return courses;
}
private static async Task<List<Course>> GetCoursesAsync()
{
return await Task.FromResult(
new List<Course>() {
new Course{
CourseNumber = "PIZZA1",
PriceGroups = new List<PriceGroup>()
},
new Course{
CourseNumber = "PIZZA2",
PriceGroups = new List<PriceGroup>()
},
new Course{
CourseNumber = "PIZZA3",
PriceGroups = new List<PriceGroup>()
},
}
);
}
private static async Task<List<PriceGroup>> GetPriceGroups()
{
return await Task.FromResult(
new List<PriceGroup>() {
new PriceGroup{
Id = 1,
CourseNumber = "PIZZA1"
},
new PriceGroup{
Id = 2,
CourseNumber = "PIZZA2"
},
new PriceGroup{
Id = 3,
CourseNumber = "PIZZA3"
},
new PriceGroup{
Id = 4,
CourseNumber = "PIZZA1"
}
}
);
}
}
public class Course
{
public string CourseNumber { get; set; }
public List<PriceGroup> PriceGroups { get; set; }
}
public class PriceGroup
{
public int Id { get; set; }
public string CourseNumber { get; set; }
}

How to import data from csv to elasticsearch in java without using logstash?

I want to import data from a csv file to elasticsearch. But I don't want to use logstatsh. So, what are the ways I can do this ?
Any blogs ? Docs ?
I came across TransportClient, but I'm not getting the point from where to start .
Thanks in advance.
very late answer, however :) ….This is for elasticsearch 7.6.0
//this class for keeping csv each row values
public class Document {
private String id;
private String documentName;
private String name;
private String title;
private String dob;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDocumentName() {
return documentName;
}
public void setDocumentName(String documentName) {
this.documentName = documentName;
}
public String getName() {
return name1;
}
public void setName(String name1) {
this.name1 = name1;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDob() {
return dob;
}
public void setDob(String dob) {
this.dob = dob;
}
}
public void bulkInsert() {
long starttime = System.currentTimeMillis();
logger.debug("ElasticSearchServiceImpl => bulkInsert Service Started");
BufferedReader br = null;
String line = "";
String cvsSplitBy = ",";
BulkRequest request;
Document document;
//elastic Search Index Name
String esIndex = "post";
try {
br = new BufferedReader(new FileReader(<path to CSV>));
request = new BulkRequest();
while ((line = br.readLine()) != null) {
// use comma as separator
String[] row = line.split(cvsSplitBy);
if(row.length >= 1) {
//filling Document object using csv columns array
document = getDocEntity(row);
//adding each filled obect into BulkRequest
request.add(getIndexRequest(document, esIndex));
} else {
logger.info("ElasticSearchServiceImpl => bulkInsert : null row ="+row.toString());
}
}
br.close();
if(request.numberOfActions()>0) {
BulkResponse bulkResponse = client.bulk(request, RequestOptions.DEFAULT);
if(bulkResponse.hasFailures()) {
logger.error("ElasticSearchServiceImpl => bulkInsert : Some of the record has failed.Please reinitiate the process");
} else {
logger.info("ElasticSearchServiceImpl => bulkInsert : Success");
}
} else {
logger.info("ElasticSearchServiceImpl => bulkInsert : No request for BulkInsert ="+request.numberOfActions());
}
} catch (Exception e) {
logger.error("ElasticSearchServiceImpl => bulkInsert : Exception =" + e.getMessage());
}
long endTime = System.currentTimeMillis();
logger.info("ElasticSearchServiceImpl => bulkInsert End" + Util.DB_AVG_RESP_LOG + "" + (endTime - starttime));
}
public static Document getDocEntity(String[] row)throws Exception {
Document document = new Document();
document.setId(UUID.randomUUID().toString());
for(int i=0;i<row.length;i++) {
switch (i) {
case 0:
document.setDocumentName(row[i]);
break;
case 1:
document.setName(row[i]);
break;
case 7:
document.setTitle(row[i]);
break;
case 8:
document.setDob(row[i]);
break;
}
return document;
}
public static IndexRequest getIndexRequest(Document document,String index)throws Exception {
IndexRequest indexRequest = null;
Map<String, Object> jsonMap = new HashMap<>();
jsonMap.put("doc_name",document.getDocumentName());
jsonMap.put("title",document.getTitle());
jsonMap.put("dob",document.getDob());
indexRequest = new IndexRequest(index).id(document.getId()).source(jsonMap);
return indexRequest;
}
If you need to show each response, you can use the following code for responses
for (BulkItemResponse bulkItemResponse : bulkResponse) {
DocWriteResponse itemResponse = bulkItemResponse.getResponse();
switch (bulkItemResponse.getOpType()) {
case INDEX:
case CREATE:
IndexResponse indexResponse = (IndexResponse) itemResponse;
break;
}
}
For more information please read official link

Object reference not set to an instance of an object in view model

I get this error:
Object reference not set to an instance of an object.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.
Source Error:
Line 251: ManageAccount.Instance.GetUserAccounts(username), "accountID", "name", accountFrom);
Line 252:
Line 253: Currencies = new SelectList(
Line 254: ManageCurrency.Instance.getCurrencies(), "id", "name",_Account.currency1.id);
Line 255:
It gives the error in this viewModel
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using Common;
using Business;
using System.Web.Mvc;
using System.Web.Security;
using System.Runtime.Remoting.Contexts;
namespace internetBankingApplication.ViewModel
{
public class NewFixedAccountViewModel
{
private account _Account { get; set; }
private fixedAccount _FixedAccount { get; set; }
public SelectList AccountTypes { get; set; }
public SelectList Durations { get; set; }
public SelectList AccountFromList { get; set; }
public SelectList Currencies { get; set; }
public int ID
{
get
{
return _Account.accountID;
}
}
[Required]
[Display(Name = "Account Name")]
public string Name
{
get
{
return _Account.name;
}
set
{
_Account.name = value;
}
}
[Required]
[Display(Name = "Account From")]
public int accountFrom { get;set;}
public string AccountFromName
{
get
{
string result = string.Empty;
try
{
result = ManageAccount.Instance.GetAccountBYID(accountFrom).name;
}
catch { }
return result;
}
}
[Required]
[Display(Name = "Duration")]
public int duration
{
get
{
return _FixedAccount.duration;
}
set
{
_FixedAccount.duration = value;
}
}
public string durationName
{
get
{
string result = string.Empty;
try
{
result = ManageDuration.Instance.GetDurationById(_FixedAccount.duration).duration1;
}
catch { }
return result;
}
}
[Required]
[Display(Name = "Available Balance")]
public decimal AvailableBalance
{
get
{
return _Account.availableBalance;
}
set
{
_Account.availableBalance = value;
}
}
[Required]
[Display(Name = "Currency")]
public int currency
{
get
{
return _Account.currency;
}
set
{
_Account.currency = value;
}
}
public string CurrencyName
{
get
{
string result = string.Empty;
try
{
result = ManageCurrency.Instance.getTypesByID(_Account.currency).name;
}
catch { }
return result;
}
}
[Required]
[Display(Name = "Account Description")]
public string Description
{
get
{
return _Account.description;
}
set
{
_Account.description = value;
}
}
[Required]
[Display(Name = "Account Renew")]
public bool renew
{
get
{
if (_FixedAccount.renew == 0)
{
return false;
}
return true;
}
set
{
if (value == false)
{
_FixedAccount.renew = 0;
}
else
{
_FixedAccount.renew = 1;
}
}
}
public NewFixedAccountViewModel()
{
// AccountTypes = new SelectList(
//ManageAccountType.Instance.getTypes(), "id", "type", _Account.typeID);
string username = HttpContext.Current.User.Identity.Name.ToString();
AccountFromList = new SelectList(
ManageAccount.Instance.GetUserAccounts(username), "accountID", "name", accountFrom);
**Currencies = new SelectList(
ManageCurrency.Instance.getCurrencies(), "id", "name",_Account.currency1.id);** //Giving the error
Durations = new SelectList(
ManageDuration.Instance.GetAllDurations(), "id", "duration", _FixedAccount.duration);
}
public NewFixedAccountViewModel(string username)
{
AccountTypes = new SelectList(
ManageAccountType.Instance.getTypes(), "id", "type", _Account.typeID);
AccountFromList = new SelectList(
ManageAccount.Instance.GetUserAccounts(username), "accountID", "name", accountFrom);
Currencies = new SelectList(
ManageCurrency.Instance.getCurrencies(), "id", "name", _Account.currency);
Durations = new SelectList(
ManageDuration.Instance.GetAllDurations(), "id", "duration", _FixedAccount.duration);
}
public NewFixedAccountViewModel(int accountID, string username)
{
_Account = ManageAccount.Instance.GetAccountBYID(accountID);
_FixedAccount = ManageFixedAccount.Instance.GetFixedAccountByID(accountID);
AccountFromList = new SelectList(
ManageAccount.Instance.GetUserAccounts(username), "accountID", "name", accountFrom);
AccountTypes = new SelectList(
ManageAccountType.Instance.getTypes(), "id", "type", _Account.accountType);
Currencies = new SelectList(
ManageCurrency.Instance.getCurrencies(), "id", "name", _Account.currency);
Durations = new SelectList(
ManageDuration.Instance.GetAllDurations(), "id", "duration", _FixedAccount.duration);
}
}
}
The error message you are getting means that you are trying to call a method or property on a null value - which you can't do.
From what I can see, either ManageCurrency is null or ManageCurrency.Instance is null.
If ManageCurrency is null the call to the Property Instance fails, as null objects have no methods or properties. Similarly, if ManageCurrency.Instance is null, the call to the Method getCurrencies fails for the same reason.
In any case - this is not too hard to debug. As skumar suggests, set a breakpoint on that line, run in debug mode, and see where the null value is, and then work backwards to discover why the value is null.
The username you are passing in the following code could be Empty or Invalid. That is why it returns NULL and above exception occurs.
AccountFromList = new SelectList(
ManageAccount.Instance.GetUserAccounts(username), "accountID", "name", accountFrom);

Filter a Collection on LINQ with Recursion

I have a collection named as MenuItemCollection and this derived form List< MenuItem >
There is a Singleton Instance of MenuItemCollection and if I simplify the fields of MenuItem:
public class MenuItem
{
int Id {set;get;}
string Title {set;get;}
MenuItemCollection ChildMenus {set;get;}
}
I need to use a filter method on this collection. For example, I'd like to filter the collection for one menu's Id.
Here is a sample MenuItemCollection:
1-Home
2-User Menu
4-Update Info
5-Delete Account
3-News
6-Archived News
As you can see there some Child menus such as number 4 or number 6
I normally use below to filter:
public List<MenuItem> Filter(MenuItemFilterArgs args)
{
List<MenuItem> Result = new List<MenuItem>();
IQueryable<MenuItem> QueryableTemp = this.AsQueryable();
return (from item in QueryableTemp
orderby item.Ordering descending
select item).ToList<MenuItem>();
}
And calling this method as:
var FilteredMenus = MenuItemCollection.GetInstance.Filter(new MenuItemFilterArgs { Id = 5 });
Since number 5 is in an inner collection under number 2 menuitem, the result returns as 0. It cannot be found.
How is it possible to run the filter recursively through inner MenuItemCollections? Could you write a code sample?
PS: If you must know why I'm using a singleton instance; my idea was
to retrieve the menus from database and keep it as an object for
easier and faster usage on run-time.
Any help would be highly appreciated.
Thanks in advance
Here is a working example. The ExtensionMethods.Map method is what you need.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
namespace WindowsFormsApplication1
{
static class Program
{
[STAThread]
static void Main()
{
var menuItems1 = MenuItemCollection.Instance.Filter(null);
var menuItems2 = MenuItemCollection.Instance.Filter(new MenuItemCriteria { Id = 5 });
var menuItems3 = MenuItemCollection.Instance.Filter(new MenuItemCriteria { Title = "News" });
var menuItems4 = MenuItemCollection.Instance.Filter(new MenuItemCriteria { Title = "News", IsTrash = true });
}
}
public class MenuItemCollection : List<MenuItem>
{
public static readonly MenuItemCollection Instance;
static MenuItemCollection()
{
Instance = GetMenuList();
}
static MenuItemCollection GetMenuList()
{
return new MenuItemCollection {
new MenuItem {Id = 1, Title = "Home"},
new MenuItem {Id = 2, Title = "User Menu", ChildMenus = new MenuItemCollection {
new MenuItem { Id = 4, Title = "Update Info"},
new MenuItem { Id = 5, Title = "Delete"}
}},
new MenuItem {Id = 3, Title = "News", ChildMenus = new MenuItemCollection {
new MenuItem { Id = 6, Title = "Archived News"},
new MenuItem { Id = 6, Title = "Trashy News", IsTrash = true}
}},
};
}
public List<MenuItem> Filter(MenuItemCriteria criteria)
{
var expression = PredicateBuilder.True<MenuItem>();
if(criteria != null)
{
if (criteria.Id.HasValue)
{
expression = expression.And(menuItem => menuItem.Id == criteria.Id);
}
if (!string.IsNullOrEmpty(criteria.Title))
{
expression = expression.And(menuItem => menuItem.Title.Contains(criteria.Title));
}
if (criteria.IsTrash.HasValue)
{
expression = expression.And(menuItem => menuItem.IsTrash == criteria.IsTrash);
}
}
Func<MenuItem, bool> searchCriteria = expression.Compile();
Func<MenuItem, IEnumerable<MenuItem>> childrenSelector = x => x.ChildMenus;
return this.Map(searchCriteria, childrenSelector).ToList();
}
}
public class MenuItemCriteria
{
public int? Id { set; get; }
public string Title { set; get; }
public bool? IsTrash { set; get; }
}
public class MenuItem
{
public int Id { set; get; }
public string Title { set; get; }
public bool IsTrash { set; get; }
public MenuItemCollection ChildMenus { set; get; }
}
public static class ExtensionMethods
{
public static IEnumerable<T> Map<T>(this IEnumerable<T> source,
Func<T, bool> selector = null,
Func<T, IEnumerable<T>> childrenSelector = null)
{
if (source == null) return new List<T>();
if (selector == null)
{
// create a default selector that selects all items
selector = x => true;
}
var list = source.Where(selector);
if (childrenSelector != null)
{
foreach (var item in source)
{
list = list.Concat(childrenSelector(item).Map(selector, childrenSelector));
}
}
return list;
}
}
public static class PredicateBuilder
{
public static Expression<Func<T, bool>> True<T>() { return f => true; }
public static Expression<Func<T, bool>> False<T>() { return f => false; }
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>
(Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
}
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>
(Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
}
}
}

Resources