Below expression compares property NAME with the value PETER.
ParameterExpression pe = Expression.Parameter(typeof(T), "x");
MemberExpression member = Expression.Property(pe, "name");
ConstantExpression value = Expression.Constant("Peter");
exp = Expression.Equal(member, value);
What if the property is a class:
public class Address
{
public string Name {get; set;}
}
Then the expression would look something similar to this:
MemberExpression member = Expression.Property(pe, "Address.Name");
ConstantExpression value = Expression.Constant("Peter");
exp = Expression.Equal(member, value);
This would fail because the member type doesn't match the value type.
So, the question is: How to build an Expression that would work using the above class sample ??
I use this expression in a NHibernate.Linq query:
var q = from f in data //of type IQueryable<T>
select f;
if (filter != null) //filter of type Expression<Func<T, bool>>
q = q.Where(filter);
etc....
Thank you.
UPDATE by Peter:
Based on the code from xanatos (next post) I have created the following test to understand how it works. Its not very different from what xanatos do, but at first I could not get it to work, so I decided to write it allover in one simple test, and that did it. With thanks to xanatos:
[Test]
public void FilterWithDeepProperties()
{
//Arrange
IGenericGridRepository repository = ObjectFactory.GetInstance<IGenericGridRepository>();
FilterDescriptor filter = new FilterDescriptor("AgreementId.Name", FilterOperator.IsEqualTo, "a name");
string[] properties = filter.Member.Split('.');
ParameterExpression pe = Expression.Parameter(typeof(SampleDomain), "x");
//Act
Expression lastMember = pe;
for (int i = 0; i < properties.Length; i++)
{
MemberExpression member = Expression.Property(lastMember, properties[i]);
lastMember = member;
}
ConstantExpression valueExpression = Expression.Constant(filter.Value);
Expression equalityExpression = Expression.Equal(lastMember, valueExpression);
Expression<Func<SampleDomain, bool>> where = Expression.Lambda<Func<SampleDomain, bool>>(equalityExpression, pe);
var result = repository.GetObjects<SampleDomain>(filter: where);
//Assert
result.Count().Should().BeGreaterThan(0, "because there are many schedule items equals to " + filter.Value);
}
typeof(T)
is already a type (a class for example), so in your exampletypeof(T)
istypeof(Address)
... unless there is an over-objectPerson
that has anAddress
that has astring Name
... – Montford