Reputation: 3816
I have a collection of Employee class and employee class has few properties like departement,manager name,payscale,designation etc.Now in my webapi, i have a search method in which i am searching a string across all fields of webapi
like if I search Peter it'll search in all fields(departement,manager_name,payscale,designation) of all employees.For this i am using below:-
public IEnumerable<Employee> Search(string searchstr)
{
if (repository != null)
{
var query =
from employees in repository.GetEmployees()
where
(employees.departement != null && employees.departement.Contains(searchstr)) ||
(employees.payscale != null && employees.payscale.Contains(searchstr))
(movie.designation != null && movie.designation.Contains(searchstr)) )
select employees;
return query.AsEnumerable().OrderBy(c => c.employeeid);
}
else
{
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
}
}
Though i am getting desired result,i have not to use that query.Is there any other way to rewrite same query?
Upvotes: 0
Views: 1288
Reputation: 1023
As stated by Noctis, using reflection results in a heavy task for the .NET runtime.
Here is some example code that loops trough all properties of a class and searchs a string concidence. It uses reflection ;)
Any questions, leave a comment asking!
The code in the entry point of the APP:
[STAThread]
private static void Main(string[] args)
{
var person1 = new Person {Name = "The first name", Address = "The first address"};
var person2 = new Person {Name = "The second name", Address = "The second address"};
var results = SearchStringTroughAllProperties("second", new List<Person> {person1, person2});
}
The Person
class:
class Person
{
public string Name { get; set; }
public string Address { get; set; }
}
And the SearchStringTroughAllProperties
method:
private static IEnumerable<Person> SearchStringTroughAllProperties(string stringToSearch,
IEnumerable<Person> persons)
{
var properties =
typeof (Person).GetProperties()
.Where(x => x.CanRead && x.PropertyType == typeof (string))
.Select(x => x.GetMethod)
.Where(x => !x.IsStatic)
.ToList();
return persons.Where(person =>
properties.Select(property => (string) property.Invoke(person, null) ?? string.Empty)
.Any(propertyValueInInstance => propertyValueInInstance.Contains(stringToSearch)));
}
Notice that:
EDIT:
For searching the string coincidence in a string
or string[]
property, change SearchStringTroughAllProperties
method to this (it gets longer!):
static IEnumerable<Person> SearchStringTroughAllProperties(string stringToSearch, IEnumerable<Person> persons)
{
var properties =
typeof (Person).GetProperties()
.Where(x => x.CanRead && (x.PropertyType == typeof (string) || x.PropertyType == typeof(string[])))
.Select(x => x.GetMethod)
.Where(x => !x.IsStatic)
.ToList();
foreach (var person in persons)
{
foreach (var property in properties)
{
bool yieldReturned = false;
switch (property.ReturnType.ToString())
{
case "System.String":
var propertyValueStr = (string) property.Invoke(person, null) ?? string.Empty;
if (propertyValueStr.Contains(stringToSearch))
{
yield return person;
yieldReturned = true;
}
break;
case "System.String[]":
var propertyValueStrArr = (string[]) property.Invoke(person, null);
if (propertyValueStrArr != null && propertyValueStrArr.Any(x => x.Contains(stringToSearch)))
{
yield return person;
yieldReturned = true;
}
break;
}
if (yieldReturned)
{
break;
}
}
}
}
Upvotes: 1
Reputation: 11783
Even though work, it feels a bit dirty. I would consider maybe using reflection to get the properties of the class, and then dynamically search them.
The benefit would be: if you add a new property tomorrow, there's nothing else you need to change.
The disadvantage would be: probably not as performant since reflection is much slower than simply searching for things you know exist.
Having said that, i'm sure there are some other nifty advanced linq tricks that maybe others can point out.
I thought I have some handy code but I don't. I wouldn't like to write it of the top of my head, because it probably won't compile (you need to get the syntax right). Have a look at the above link :)
Upvotes: 0