LINQ 포맷터
29777 단어 csharpwebdevexpressionslinq
우선 메모리에 있는 개체나 데이터베이스 쿼리에 서식 규칙을 적용할 수 있습니다. 이상적으로는 도구가 두 시나리오를 모두 지원해야 합니다. 운 좋게도 표현 트리가 우리를 위해 일할 수 있습니다. 다음과 같은 코드를 작성할 때:
queryable.Select(x => x.FirstName + " " + x.LastName).ToList();
// Expression<Func<Employee, String>>
그리고
enumerable.Select(x => x.FirstName + " " + x.LastName).ToList();
// Func<Employee, String>
x => x.Name
람다의 유형은 처음에는 동일하게 보이지만 서로 다릅니다. 원하는 경우 차이점을 더 잘 이해하려면 내 이야기를 확인하십시오.목적을 위해
Expression<Func<Employee, String>>
유형이 필요합니다.public class Formatter<T>
{
private readonly Expression<Func<T, string>> _expression;
public Formatter(Expression<Func<T, string>> expression)
{
_expression = expression
?? throw new ArgumentNullException(nameof(expression));
}
public static implicit operator
Formatter<T>(Expression<Func<T, string>> expresssion)=>
new Formatter<T>(expresssion);
public static implicit operator
Expression<Func<T, string>>(Formatter<T> formatter) =>
formatter._expression;
public string Format(T obj) =>
(_func ?? (_func = _expression.Compile())).Invoke(obj);
}
여기서는 해당 식에서/로의 변환을 재정의하므로 둘 다:
Formatter<Employee> formatter =
(Expression<Func<Employee, String>>)
x => x.FirstName + " " + x.LastName;
그리고
queryable.Select(formatter).ToList();
잘 작동합니다.
메모리 내 개체에서 사용하려면
Format
함수를 사용합니다.string formattedLastName = formatter.Format(obj);
계층 관리
여태까지는 그런대로 잘됐다. 그러나 직원 계정에 동일한 형식을 사용해야 하는 경우에는 어떻게 해야 합니까?
public class Account
{
public Employee Employee { get; set; }
}
다음과 같이 사용할 수 있습니다.
accounts.Select(x => employeeFormatter.Format(x.Employee));
그러나 이 코드는 형식 메시지의 본문을 포함하는 표현식이 필요한 동안 캡처
InvocationExpression
하기 때문에 제대로 변환되지 않습니다. 간단히 말해서 대상 표현식에서 다른 표현식을 빌드하는 방법이 필요합니다.public Formatter<TParent> From<TParent
(Expression<Func<TParent, T>> map) =>
new Formatter<TParent>(
Expression.Lambda<Func<TParent, string>>(
Expression.Invoke(_expression, map.Body),
map.Parameters.First()));
이 문단이 이해가 안 되시면 체크해주세요. 여기에는 약간의 코드 연결이 필요하므로 이 문제에 대한 간단한 설명이 없습니다.
이제
From
메서드를 사용하여 Employee 포맷터를 사용하여 AccountFormatter
를 빌드할 수 있습니다.var employeeFormatter = (Expression<Func<Employee, String>>)
x => x.FirstName + " " + x.LastName;
var accountFormatter =
employeeFormatter.From(x => x.Employee);
accounts.Select(accountFormatter).ToList();
데이터 매퍼(Automapper/Mapster 등)
데이터 매퍼의 팬이라면 추가 확장 방법으로 구현을 향상시킬 수 있습니다. 다음은 AutoMapper의 예입니다.
public static class AutomapperFormatterExtensions
{
public static void FormatWith<TSource, TDest>(
this IMemberConfigurationExpression<TSource, TDest, string> mapperConfiguration,
Formatter<TSource> formatter) =>
mapperConfiguration.MapFrom<string>(formatter);
public static void FormatWith<TSource, TDest>(
this IPathConfigurationExpression<TSource, TDest, string> mapperConfiguration,
Formatter<TSource> formatter) =>
mapperConfiguration.MapFrom<string>(formatter);
public static Action<IMemberConfigurationExpression<TSource, TDest, string>> ToMapping<TSource, TDest>(
this Formatter<TSource> formatter) =>
x => x.FormatWith(formatter);
public static IMappingExpression<TSource, TDestination> ForMember<TSource, TDestination>(
this IMappingExpression<TSource, TDestination> mappingExpression,
Expression<Func<TDestination, string>> destinationMember,
Formatter<TSource> formatter) =>
mappingExpression.ForMember(
destinationMember,
formatter.ToMapping<TSource, TDestination>());
public static IMappingExpression<TSource, TDestination> ForName<TSource, TDestination>(
this IMappingExpression<TSource, TDestination> mappingExpression,
Formatter<TSource> formatter) =>
where TDestination : IHasName
mappingExpression.ForMember(
x => x.Name,
formatter.ToMapping<TSource, TDestination>());
}
완전한 솔루션은 다음과 같습니다.
public class Formatter<T>
{
private readonly Expression<Func<T, string>> _expression;
private Func<T, string> _func { get; set; }
public Formatter(Expression<Func<T, string>> expression)
{
_expression = expression ?? throw new ArgumentNullException(nameof(expression));
}
public Formatter<TParent> From<TParent>(Expression<Func<TParent, T>> map)
=> new Formatter<TParent>(Expression.Lambda<Func<TParent, string>>(
Expression.Invoke(_expression, map.Body), map.Parameters.First()));
public static implicit operator Formatter<T>(Expression<Func<T, string>> expresssion) =>
new Formatter<T>(expresssion);
public static implicit operator Expression<Func<T, string>>(Formatter<T> formatter) => formatter._expression;
public string Format(T obj) => (_func ?? (_func = _expression.AsFunc())).Invoke(obj);
}
public static class AutomapperFormatterExtensions
{
public static void FormatWith<TSource, TDest>(
this IMemberConfigurationExpression<TSource, TDest, string> mapperConfiguration,
Formatter<TSource> formatter) =>
mapperConfiguration.MapFrom<string>(formatter);
public static void FormatWith<TSource, TDest>(
this IPathConfigurationExpression<TSource, TDest, string> mapperConfiguration,
Formatter<TSource> formatter) =>
mapperConfiguration.MapFrom<string>(formatter);
public static Action<IMemberConfigurationExpression<TSource, TDest, string>> ToMapping<TSource, TDest>(
this Formatter<TSource> formatter) =>
x => x.FormatWith(formatter);
public static IMappingExpression<TSource, TDestination> ForMember<TSource, TDestination>(
this IMappingExpression<TSource, TDestination> mappingExpression,
Expression<Func<TDestination, string>> destinationMember,
Formatter<TSource> formatter) =>
mappingExpression.ForMember(destinationMember, formatter.ToMapping<TSource, TDestination>());
public static IMappingExpression<TSource, TDestination> ForName<TSource, TDestination>(
this IMappingExpression<TSource, TDestination> mappingExpression,
Formatter<TSource> formatter) =>
where TDestination : IHasName
mappingExpression.ForMember(x => x.Name, formatter.ToMapping<TSource, TDestination>());
}
즐거운 코딩하세요!
Reference
이 문제에 관하여(LINQ 포맷터), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/maxarshinov/linq-formatters-4i07텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)