score:0
This is the Reflection route (using LINQ to Objects):
static readonly IEnumerable<PropertyInfo> otherProps = typeof (TOther).GetProperties();
public void DoSomething (TOther thatBar)
{
var foo = Items
.Select (item => item.Bar)
.Single (thisBar =>
otherProps.All (prop =>
prop.GetValue (thisBar, null).Equals (
prop.GetValue (thatBar, null)
)
)
);
}
And be sure to watch for corner cases (e.g. indexer properties, properties you don't want to match, set-only properties, properties that can throw exceptions).
I didn't check if it compiles though so you might want to tweak the method so it does the right thing.
However, you should not do that if:
- you need this in more than one place;
Items
is not an in-memory list or array but a query result, as in LINQ to SQL;- you need to do it considerably fast.
After all, according to Information Expert principle, since concrete Bar
types “know” themselves better than any other classes, they should be given the responsibility to provide a comparison implementation.
score:1
If this is for LINQ-to-SQL etc, maybe something like:
static Expression<Func<T,bool>> GetComparer<T>(T obj)
{
var c = Expression.Constant(obj, typeof(T));
var param = Expression.Parameter(typeof(T), "x");
var members = (
from member in typeof(T).GetMembers(BindingFlags.Instance | BindingFlags.Public)
where member.MemberType == MemberTypes.Field || member.MemberType == MemberTypes.Property
select Expression.Equal(Expression.MakeMemberAccess(c, member),
Expression.MakeMemberAccess(param, member))).ToList();
Expression body;
if(members.Count == 0) body = Expression.Constant(true, typeof(bool));
else body = members.Aggregate((x,y) => Expression.AndAlso(x,y));
return Expression.Lambda<Func<T,bool>>(body, param);
}
You can use that with LINQ-to-Objects too if you use .AsQueryable()
first.
For example,
class Test
{
public int Foo { get; set; }
public string Bar { get; set; }
}
static void Main()
{
var data = new[] {
new Test { Foo = 1, Bar = "a"}, new Test { Foo = 1, Bar = "b"},
new Test { Foo = 2, Bar = "a"}, new Test { Foo = 2, Bar = "b"},
new Test { Foo = 1, Bar = "a"}, new Test { Foo = 1, Bar = "b"},
new Test { Foo = 2, Bar = "a"}, new Test { Foo = 2, Bar = "b"},
};
var findMe = new Test { Foo = 1, Bar = "b" };
var found = data.AsQueryable().Where(GetComparer(findMe)).ToList();
// finds 2 items, as expected
}
or alternatively, via .Compile()
:
var found = data.Where(GetComparer(findMe).Compile()).ToList();
// finds 2 items, as expected
score:2
You can either implement IComparable
(as Oskar suggested) or you need to use reflection.
If you're using reflection and you need to speed-up your code then you can emit dynamic IL (System.Reflection.Emit) at run-time. See Dapper source for an example of dynamic IL generation.
Source: stackoverflow.com
Related Query
- C# LINQ - Select statement that compares all properties of a class with a different instance of the same class?
- How can I set properties on all items from a linq query with values from another object that is also pulled from a query?
- Linq query to return all records with select new statement
- linq how to select a parent with a child collection that contains all of an array (or list) of values
- LINQ select with EF Core and cast to derived class without copying properties
- Select All records of a class with LINQ query
- Select all columns on an object with Linq
- Recursive LINQ query: select item and all children with subchildren
- linq how to select a parent with a child collection that contains one or many of an array (or list) of values
- Select all unique combinations of a single list, with no repeats, using LINQ
- Using LINQ to search a byte array for all subarrays that start/stop with certain byte
- Using Linq to Select properties of class to return IEnumerable<T>
- How to Select All with a One to Many Relationship Using Linq
- Dynamically generate LINQ select with nested properties
- Select all rows with distinct column value using LINQ
- Select all unique combinations of a single list, with no repeats, using LINQ (Part 2)
- LINQ select new class with a name
- LINQ select all items of all subcollections that contain a string
- C# Create object with dynamic properties : LINQ select List<object> values by property names array
- Concatenate All Properties to a String with LINQ
- LINQ expression with generic class properties
- How do I do this SELECT statement that uses column renaming (or column alias) with LINQ?
- C# : LINQ query to list all empty properties of a class
- I'm trying to simplify with linq a statement that takes 2 lists of numbers and subtracts the first one from the second one
- Create a Dynamic Linq to EF Expression to Select IQueryable into new class and assign properties
- how to deal with exception in LINQ Select statement
- Using LINQ I have a list of lists, how do I select all objects that exist in every list?
- Select method missing from intellisense with Linq statement
- select from linq statement with await
- How to get the value of class properties with Linq query and IEnumerable
More Query from same tag
- C# Linq Lambda Left Join Where Right is Null
- Finding a permutation from list<int> using linq
- Linq Find all items in collection from an other collection
- find index of list with params c#
- Have a list from a sub list of objects
- Find a dupe in a List with Linq
- LINQ to JSON - Query for object or an array
- Entity Framework OrderBy().Where() expression
- Given IComparer, Zip two ordered IEnumerable-s, pairing only equal elements?
- linq count/groupby not working
- Building Dynamic LINQ Queries based on Combobox Value
- How to find the keys in dictionary object which matches partially?
- How do I sum a sub-list in linq?
- Select specific records in a c# list with a max value
- CsQuery - getting sibling values between two selectors?
- Creating a DataTable From a Linq Query in my C# Windows form
- Compare two generic lists using Linq
- How to extract a meta tag from XML/HTML using Linq?
- Performing a right outer join with a group by using linq
- .NET C# I want to get the IDs (1/multiple) from a data if it much the ID of another table
- convert foreach and if to linq queries
- How do I get value from a nested list with reflection?
- Compare datetime with millisecond precision
- Permutation between multiple arrays with null values
- LINQ include nested properties when selecting anonymous type
- Insert a value to SQL Server database with LINQ on C#
- LINQ Cannot assign void to Implicitly Typed variable
- how to find a string which is exist or not in some specific datacolumns of the datatable using LINQ query in C#?
- LINQ - Set element in Dictionary to empty where DateTime value is oldest
- get new list which contain any numeric value from current list using LINQ query