Если это для LINQ-to-SQL и т. Д., Может быть что-то вроде:
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);
}
Вы также можете использовать это с LINQ-to-Objects, если сначала используете .AsQueryable()
.
Например,
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
}
или, альтернативно, через .Compile()
:
var found = data.Where(GetComparer(findMe).Compile()).ToList();
// finds 2 items, as expected