코드에서 Linq 술어 빌드
16361 단어 dotnetcsharpexpressionsorm
public class Animal
{
public int Id { get; set; }
public string Name { get; set; }
public int Height { get; set; }
public int Weight { get; set; }
}
public class AnimalFilter
{
public string Name { get; set; }
public int? Height { get; set; }
public int? Weight { get; set; }
}
첫 번째 옵션은 필터 필드에 값이 있는지 확인하고 각 경우에 대한 술어를 만드는 것입니다.
if (!string.IsNullOrWhiteSpace(filter.Name) && !filter.Height.HasValue && !filter.Weight.HasValue)
{
var predicate = a => a.Name == filter.Name;
}
...
이 방법의 단점은 주어진 매개변수의 모든 조합에 대해 사용자 정의 술어를 작성해야 한다는 것입니다. AnimalFilter의 경우 8개의 다른 술어가 됩니다. 그러나 필터에 10, 20개의 필드가 있으면 어떻게 될까요?
또 다른 옵션은 표현식을 사용하는 것입니다. 필터 데이터를 기반으로 식을 만들고 조건자로 변환할 수 있습니다.
var parameter = Expression.Parameter(typeof(Animal));
Expression expression = Expression.Constant(true);
if (!string.IsNullOrWhiteSpace(filter.Name))
{
expression = Expression.AndAlso(
expression,
Expression.Equal(
Expression.Property(parameter, nameof(Animal.Name)),
Expression.Constant(filter.Name)
)
)
}
if (filter.Height.HasValue))
{
expression = Expression.AndAlso(
expression,
Expression.Equal(
Expression.Property(parameter, nameof(Animal.Height)),
Expression.Constant(filter.Height.Value)
)
)
}
if (filter.Weight.HasValue))
{
expression = Expression.AndAlso(
expression,
Expression.Equal(
Expression.Property(parameter, nameof(Animal.Weight)),
Expression.Constant(filter.Weight.Value)
)
)
}
var predicate = Expression.Lambda<Func<Animal, bool>>(expression, parameter);
이 방법의 장점은 필터에 추가되는 모든 새 속성에 대해 코드와 함께 하나의 조건만 추가하고 기존 속성과의 모든 조합을 만들 필요가 없다는 것입니다.
이 코드는 표현식 작성을 도우미 클래스로 이동하여 개선할 수 있습니다.
public static class PredicateExtensions
{
public static Expression And<T>(this Expression expression, ParameterExpression parameter, string propertyName, T value)
{
return Expression.AndAlso(
expression,
Expression.Equal(
Expression.Property(parameter, propertyName),
Expression.Constant(value)
)
);
}
}
그런 다음 이 코드는 다음과 같이 단순화됩니다.
var parameter = Expression.Parameter(typeof(Animal));
Expression expression = Expression.Constant(true);
if (!string.IsNullOrWhiteSpace(filter.Name))
{
expression = expression.And(parameter, nameof(Animal.Name), filter.Name);
}
if (filter.Height.HasValue))
{
expression = expression.And(parameter, nameof(Animal.Height), filter.Height);
}
if (filter.Weight.HasValue))
{
expression = expression.And(parameter, nameof(Animal.Weight), filter.Weight);
}
var predicate = Expression.Lambda<Func<Animal, bool>>(expression, parameter);
발생할 수 있는 한 가지 문제 - 필터 속성과 엔터티 속성의 유형이 서로 다른 경우(예: nullable 및 not nullable). 이 경우 상수 표현식에 일반 T 매개변수를 추가해야 합니다.
public static class PredicateExtensions
{
public static Expression And<T>(this Expression expression, ParameterExpression parameter, string propertyName, T value)
{
return Expression.AndAlso(
expression,
Expression.Equal(
Expression.Property(parameter, propertyName),
Expression.Constant(value, typeof(T))
)
);
}
}
GLHF
Reference
이 문제에 관하여(코드에서 Linq 술어 빌드), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/anton_ilin/building-linq-predicates-in-code-f8f텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)