Ниже выражения сравнивает свойство NAME со значением PETER.MemberExpression, build Expression.Property из класса
ParameterExpression pe = Expression.Parameter(typeof(T), "x");
MemberExpression member = Expression.Property(pe, "name");
ConstantExpression value = Expression.Constant("Peter");
exp = Expression.Equal(member, value);
Что делать, если свойство является класс:
public class Address
{
public string Name {get; set;}
}
Тогда выражение будет выглядеть нечто похожее на это:
MemberExpression member = Expression.Property(pe, "Address.Name");
ConstantExpression value = Expression.Constant("Peter");
exp = Expression.Equal(member, value);
Это не потому, что тип член не соответствует тип значения.
Итак, вопрос: как построить выражение, которое будет работать с использованием вышеприведенного класса?
Я использую это выражение в запросе NHibernate.Linq:
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....
Спасибо.
UPDATE Петром:
на основе коду из Ксанатоса (следующий пост) я создал следующий тест, чтобы понять, как это работает. Это не очень отличается от того, что делают 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)' уже является типом (например, классом), поэтому в вашем примере 'typeof (T)' is 'typeof (Address)' ... если не существует над-объекта 'Person', который имеет 'Адрес', который имеет 'string Name' ... – xanatos
Я получаю его, но это происходит, когда вы заканчиваете (над-объектом), как и следующий образец: выберите t. *, A.name из SomeTable t inner join AddressTable a на a.Id = t.AddressTableId, где a.name = 'Peter'. –