Я использовал вашу идею для метода расширения для OrderBy. Но в случае «многих-многих» я получаю ошибку. Например, у вас есть таблица Site, Customer и Customer_site. Для данного сайта я хочу сортировать по имени клиента и в расширении OrderBy (когда я передаю «site.customer», где клиент является навигационным свойством), я получаю ошибку в строке: propertyAccess = Expression.MakeMemberAccess (свойствоAccess, свойство);
Это то, что я использую (с некоторыми улучшениями :-)):
public static IQueryable<TEntity> OrderBy<TEntity>(this IQueryable<TEntity> source, string orderByValues) where TEntity : class
{
IQueryable<TEntity> returnValue = null;
string orderPair = orderByValues.Trim().Split(',')[0];
string command = orderPair.ToUpper().Contains("DESC") ? "OrderByDescending" : "OrderBy";
var type = typeof(TEntity);
var parameter = Expression.Parameter(type, "p");
string propertyName = (orderPair.Split(' ')[0]).Trim();
System.Reflection.PropertyInfo property;
MemberExpression propertyAccess;
if (propertyName.Contains('.'))
{
// support to be sorted on child fields.
String[] childProperties = propertyName.Split('.');
property = typeof(TEntity).GetProperty(childProperties[0]);
propertyAccess = Expression.MakeMemberAccess(parameter, property);
for (int i = 1; i < childProperties.Length; i++)
{
Type t = property.PropertyType;
if (!t.IsGenericType)
{
property = t.GetProperty(childProperties[i]);
}
else
{
property = t.GetGenericArguments().First().GetProperty(childProperties[i]);
}
propertyAccess = Expression.MakeMemberAccess(propertyAccess, property);
}
}
else
{
property = type.GetProperty(propertyName);
propertyAccess = Expression.MakeMemberAccess(parameter, property);
}
var orderByExpression = Expression.Lambda(propertyAccess, parameter);
var resultExpression = Expression.Call(typeof(Queryable), command, new Type[] { type, property.PropertyType },
source.Expression, Expression.Quote(orderByExpression));
returnValue = source.Provider.CreateQuery<TEntity>(resultExpression);
if (orderByValues.Trim().Split(',').Count() > 1)
{
// remove first item
string newSearchForWords = orderByValues.ToString().Remove(0, orderByValues.ToString().IndexOf(',') + 1);
return source.OrderBy(newSearchForWords);
}
return returnValue;
}
С уважением
Slobodan
Операторы &&
и и
имеют разный приоритет, и =
оказывается между ними.
irb(main):006:0> i = true and false
=> false
irb(main):007:0> i
=> true
irb(main):008:0> i = true && false
=> false
irb(main):009:0> i
=> false
irb(main):010:0>
Первый читается как (i = true) и false
, второй как i = (true && false)
.
Ваша строка анализируется как
i = true and false
(i = true) and false
true and false
И, конечно же, поскольку i = true
, i
будет истина
впоследствии.
Насколько я понимаю ваш код, он интерпретируется как:
Результаты кажутся правильными .
Как уже объяснялось выше, ключевое слово и
используется, когда вы хотите поместить два разных операторов в одной строке. Это просто лучший способ сделать ваш код читабельным.
Таким образом,
i = true and false
подразумевает i = true; false
#(a less widely used code layout in ruby)
или самый простой способ:
i = true
false
Итак, вывод правильный. В противном случае, если вы ожидали false
, используйте логическое значение и &&
.
и
имеет меньший приоритет, чем =
, поэтому i = true и false
разбирается как (i = true) и false
.
Таким образом, значение true
присваивается i
, а затем возвращаемое значение этой операции (которое является true) и
редактируется с false, что приводит к тому, что все выражение оценивается как false,
даже при том, что i
по-прежнему имеет значение true
.