Flexfetcher는 필터링, 정렬, 페이징 데이터를위한 .NET 라이브러리입니다. OOP 원칙을 기반으로 설계되었으며 웹, 데스크탑, 모바일 등 모든 .NET 프로젝트에서 사용할 수 있습니다. Flexfetcher는 Telerik Kendo UI 그리드 개체 형식에서 영감을 얻었습니다.
.NET : SIEVE, QUERYKIT, LIGHTQUERY 등에 필터링, 정렬, 페이징 데이터를위한 훌륭한 라이브러리가 많이 있지만 대부분은 OOP 원칙을 기반으로 설계되지 않았습니다. 여기에는 인간이 읽을 수있는 쿼리 구문이 있습니다 (모든 예제는 해당 라이브러리 문서에서 가져옵니다).
sorts=LikeCount,CommentCount,-created&filters=LikeCount>10,Title@=awesome title,&page=1&pageSize=10
또는
""(Age ^^ [20, 30, 40]) && (BirthMonth ^^* ["January", "February", "March"]) || (Id ^^ ["6d623e92-d2cf-4496-a2df-f49fa77328ee"])""
또는
`?sort=country&thenSort=email desc`
그러나 동시에 :
Flexfetcher는 해당 라이브러리보다 낫거나 나쁘지 않습니다. 단지 다릅니다. 그것은 객체의 형식으로 쿼리를 받아 들여서 다음과 같이 JSON에서 직렬화/사형화 될 수 있습니다.
?Filters={"Logic":"And","Filters":[{"Operator":"Eq","Field":"Address.Town","Value":"New York"}]}
또는 다음과 같이 더 컴팩트 한 형식을 선호하는 경우 :
?Filter={"L":"And","Fs":[{"O":"Eq","F":"Address.Town","V":"New York"}]}
또는 Post Request (RPC 스타일)를 사용하려면 다음과 같습니다.
{
"Filters" : {
"Logic" : " and " ,
"Filters" : [
{
"Operator" : " eq " ,
"Field" : " Address.Town " ,
"Value" : " New York "
}
]
}
}이 형식은 인간을 위해 읽고 이해하기 쉽고, 확장하기 쉽고, 직렬화/사형화가 쉬우 며, 기계 간 통신에 사용하기 쉽습니다.
Flexfetcher는 다음 플랫폼을 위해 빌드됩니다.
이는 .NET Core ( samples/WebApiSample 참조) 및 .NET 프레임 워크 ( samples/WebApiSample.Framework48 참조) 프로젝트에서 사용할 수 있음을 의미합니다.
Flexfetcher는 필터 및 분류기에 사용되는 필드의 다음 데이터 유형을 지원합니다.
모든 값은 무효가 될 수 있습니다.
다음 명령을 실행하여 NUGET 패키지 관리자 콘솔을 통해 Flexfetcher (NUGET)를 설치할 수 있습니다.
dotnet add package FlexFetcher
Flexfetcher.dependencyInjection.microsoft (NUGET)를 설치하려면 :
dotnet add package FlexFetcher.DependencyInjection.Microsoft
Flexfetcher.serialization.newtonsoftjson (Nuget)을 설치하려면 :
dotnet add package FlexFetcher.Serialization.NewtonsoftJson
flexfetcher.serialization.systemtextjson (nuget)을 설치하려면 :
dotnet add package FlexFetcher.Serialization.SystemTextJson
모든 예제는
tests/TestData/InMemoryDataHelper.cs에 정의 된 테스트 데이터 세트에서 수행되며tests/TestData/Database/PeopleEntity.cs및tests/TestData/Database/AddressEntity.csEntities로 구성됩니다.
Flexfetcher를 사용하는 가장 간단한 방법은 IQueryable<T> 및 IEnumerable<T> 인터페이스에 확장 방법을 사용하는 것입니다.
var filter = new DataFilter
{
Filters = new List < DataFilter >
{
new ( )
{
Field = "Name" ,
Operator = DataFilterOperator . Equal ,
Value = "John"
}
}
} ;
var result = _ctx . People . FilterData ( filter ) . ToList ( ) ; var sorter = new DataSorters
{
Sorters = new List < DataSorter >
{
new DataSorter // First sort by Surname in ascending order
{
Field = "Surname" ,
Direction = DataSorterDirection . Asc
} ,
new DataSorter // Then sort by Name in descending order
{
Field = "Name" ,
Direction = DataSorterDirection . Desc
}
}
} ;
var result = _ctx . People . SortData ( sorter ) . ToList ( ) ; var pager = new DataPager { PageSize = 3 , Page = 1 } ; // Numeration starts from 1 for Page number
OR
var pager = new DataPager { Skip = 3 , Take = 3 } ;
var result = _ctx . People . PageData ( pager ) . ToList ( ) ; 확장 방법은 간단한 경우에 좋지만 사용량은 매우 제한적입니다.
보다 복잡한 경우에는 FlexFetcher 클래스를 사용할 수 있습니다 : FlexFilter<TEntity> 및 FlexFilter<TEntity, TModel> , FlexSorter<TEntity> 및 FlexSorter<TEntity, TModel> , FlexPager<TEntity> 및 FlexPager<TEntity, TModel> , FlexFetcher<TEntity> 및 FlexFetcher<TEntity, TModel> .
권장되는 방법은 아니지만 명확하게하기 위해 수동으로 수업 인스턴스를 만드는 방법을 살펴 보겠습니다. 나중에 해당 섹션에서 의존성 주입을 살펴 보겠습니다.
var filter = new DataFilter
{
Filters = new List < DataFilter >
{
new ( )
{
Field = "Name" ,
Operator = DataFilterOperator . Equal ,
Value = "John"
}
}
} ;
var flexFilter = new FlexFilter < PeopleEntity > ( ) ;
var result = flexFilter . FilterData ( _ctx . People , filter ) . ToList ( ) ; var sorters = new DataSorters
{
Sorters = new List < DataSorter >
{
new DataSorter
{
Field = "Surname" ,
Direction = DataSorterDirection . Asc
}
}
} ;
var flexSorter = new FlexSorter < PeopleEntity > ( ) ;
var result = flexSorter . SortData ( _ctx . People , sorters ) . ToList ( ) ; var pager = new DataPager { PageSize = 3 , Page = 1 } ;
var flexPager = new FlexPager < PeopleEntity > ( ) ;
var result = flexPager . PageData ( _ctx . People , pager ) . ToList ( ) ; var pager = new DataPager { PageSize = 3 , Page = 1 } ;
var flexFetcher = new FlexFetcher < PeopleEntity > ( ) ;
var result = flexFetcher . FetchData ( _ctx . People , null , null , pager ) . ToList ( ) ; // Filter, sorter and pager parameters are optional 종속성 주입과 함께 Flexfetcher를 사용하려면 FlexFetcher.DependencyInjection.Microsoft 패키지를 설치하는 것을 잊지 마십시오.
FlexFilter, FlexSorter, FlexPager와 같은 구성 요소뿐만 아니라 주요 Flexfetcher 클래스를 주입 할 수 있습니다. 기본 사용법은 다음과 같습니다.
services . AddSingleton < FlexFetcher < PeopleEntity > > ( ) ;Flexfetcher Classes는 상태가 없으므로 싱글 톤으로 사용하는 것이 안전합니다. 그러나 당신이 그것들을 스코프 또는 일시적으로 사용하려면, 그것은 당신에게 달려 있습니다.
보다 진보 된 시나리드 필이 다음에 표시됩니다. 또한 tests/FlexFetcherTests/DependencyInjectionTests/ServiceProviderTests.cs , samples/WebApiSample ) 및 samples/WebApiSample.Framework48 의 더 많은 예를 참조하십시오.
이 예제 데이터 모델에서 우리는 객체를 중첩시켰다 : PeopleAntity에는 주소 속성이 있습니다. 중첩 된 물체로 필터링하는 방법을 살펴 보겠습니다.
var filter = new DataFilter
{
Filters = new List < DataFilter >
{
new ( )
{
Field = "Address.City" , // Address is a nested object, so we use dot notation
Operator = DataFilterOperator . Equal ,
Value = "New York"
}
}
} ;
var flexAddressFilter = new FlexFilter < AddressEntity > ( ) ;
var peopleFilterOptions = new FlexFilterOptions < PeopleEntity > ( ) ;
peopleFilterOptions . AddNestedFlexFilter ( flexAddressFilter ) ;
var flexPeopleFilter = new FlexFilter < PeopleEntity > ( peopleFilterOptions ) ;
var result = flexPeopleFilter . FilterData ( _ctx . People , filter ) . ToList ( ) ;의존성 주입으로 동일한 작업을 수행 할 수 있습니다.
Services . AddSingleton < FlexFilter < AddressEntity > > ( ) ;
Services . AddSingletonFlexOptions < FlexFilterOptions < PeopleEntity > > ( ( provider , options ) =>
{
options . AddNestedFlexFilter ( provider . GetRequiredService < FlexFilter < AddressEntity > > ( ) ) ;
} ) ;
Services . AddSingleton < FlexFilter < PeopleEntity > > ( ) ;FlexSorter, FlexPager 및 Flexfetcher에도 동일한 원칙을 적용 할 수 있습니다.
tests/FlexFetcherTests/DependencyInjectionTests/ServiceProviderTests.cs 및 samples/WebApiSample 의 더 많은 예를 참조하십시오.
이전 예제에서는 하나의 필터 만 사용했지만 다음과 같은 OR 또는 논리와 함께 여러 필터를 사용할 수 있습니다.
var filter = new DataFilter
{
Logic = DataFilterLogic . Or ,
Filters = new List < DataFilter >
{
new ( )
{
Field = "Name" ,
Operator = DataFilterOperator . Equal ,
Value = "John"
} ,
new ( )
{
Logic = DataFilterLogic . And ,
Filters = new List < DataFilter >
{
new ( )
{
Field = "Name" ,
Operator = DataFilterOperator . Equal ,
Value = "Jane"
} ,
new ( )
{
Field = "Age" ,
Operator = DataFilterOperator . GreaterThan ,
Value = 55
}
}
}
}
} ;FlexFilter는 깊이로 중첩 필터를 지원합니다.
로직이 지정되지 않은 경우 기본적으로 설정됩니다.
필터에는 (필터 및 로직) 또는 (필드, 연산자 및 값) 속성이 포함될 수 있지만 둘 다가 아닙니다.
우리는 이미 평등 한 연산자가있는 예를 보았지만 더 많은 운영자가 있습니다.
new DataFilter { Field = "Name" , Operator = DataFilterOperator . Equal , Value = "John" } new DataFilter { Field = "Name" , Operator = DataFilterOperator . NotEqual , Value = "John" } new DataFilter { Field = "Age" , Operator = DataFilterOperator . GreaterThan , Value = 55 } new DataFilter { Field = "Age" , Operator = DataFilterOperator . GreaterThanOrEqual , Value = 55 } new DataFilter { Field = "Age" , Operator = DataFilterOperator . LessThan , Value = 55 } new DataFilter { Field = "Age" , Operator = DataFilterOperator . LessThanOrEqual , Value = 55 } new DataFilter { Field = "Name" , Operator = DataFilterOperator . Contains , Value = "Jo" } new DataFilter { Field = "Name" , Operator = DataFilterOperator . StartsWith , Value = "Jo" } new DataFilter { Field = "Name" , Operator = DataFilterOperator . EndsWith , Value = "hn" } new DataFilter { Field = "Age" , Operator = DataFilterOperator . In , Value = new List < int > { 55 , 56 , 57 } } 자체 필터 연산자를 만들려면 다음이 필요합니다.
BaseFilterExpressionHandler 에서 억제 된 사용자 정의 FilterexpressionHandler를 만듭니다FilterExpressionBuilder 에서 억제 된 사용자 정의 FilterexpressionBuilder를 만듭니다AddCustomExpressionHandlers 메소드를 재정의하십시오 다음과 같이 보일 수 있습니다 ( tests/FlexFetcherTests/FlexFilterTests/CustomFilterExpressionBuilderTests.cs 참조 : :
class CustomExpressionBuilderWithValueTest : FilterExpressionBuilder < PeopleEntity >
{
protected override void AddCustomExpressionHandlers ( List < IFilterExpressionHandler > handlers )
{
handlers . Add ( new ModuleFilterExpressionHandler ( ) ) ;
}
private class ModuleFilterExpressionHandler : BaseFilterExpressionHandler
{
public override string Operator => "MODULE" ;
public override Expression BuildExpression ( Expression property , DataFilter filter )
{
var value = BuildValueExpression ( filter ) ;
return Expression . Equal ( Expression . Modulo ( property , value ) , Expression . Constant ( 0 ) ) ;
}
}
}
var customExpressionBuilder = new CustomExpressionBuilderWithValueTest ( ) ;
var options = new FlexFilterOptions < PeopleEntity > ( customExpressionBuilder ) ;
var flexFilter = new FlexFilter < PeopleEntity > ( options ) ;
var filter = new DataFilter
{
Logic = DataFilterLogic . And ,
Filters = new List < DataFilter >
{
new ( )
{
Field = "Age" ,
Operator = "Module" ,
Value = 15
}
}
} ;
var result = flexFilter . FilterData ( _ctx . People , filter ) . ToList ( ) ;또한 값이 필요한 사용자 정의 필터 연산자를 만들 수 있습니다.
class CustomExpressionBuilderWithoutValueTest : FilterExpressionBuilder < PeopleEntity >
{
protected override void AddCustomExpressionHandlers ( List < IFilterExpressionHandler > handlers )
{
handlers . Add ( new EvenNumberFilterExpressionHandler ( ) ) ;
}
private class EvenNumberFilterExpressionHandler : BaseFilterExpressionHandler
{
public override string Operator => "EVEN" ;
public override Expression BuildExpression ( Expression property , DataFilter filter )
{
return Expression . Equal ( Expression . Modulo ( property , Expression . Constant ( 2 , property . Type ) ) , Expression . Constant ( 0 ) ) ;
}
}
}
var customExpressionBuilder = new CustomExpressionBuilderWithoutValueTest ( ) ;
var options = new FlexFilterOptions < PeopleEntity > ( customExpressionBuilder ) ;
var flexFilter = new FlexFilter < PeopleEntity > ( options ) ;
var filter = new DataFilter
{
Logic = DataFilterLogic . And ,
Filters = new List < DataFilter >
{
new ( )
{
Field = "Age" ,
Operator = "Even" ,
Value = null
}
}
} ;
var result = flexFilter . FilterData ( _ctx . People , filter ) . ToList ( ) ; 종속성 주입과 같은 사용법은 다음과 같습니다 ( tests/FlexFetcherTests/DependencyInjectionTests/ServiceProviderTests.cs , GenericFlexFilterWithExpressionBuilderUsage() 메소드 참조) :
class CustomExpressionBuilder : FilterExpressionBuilder < PeopleEntity > ;
class GenericFlexFilterService ( FlexFilter < PeopleEntity > flexFilter )
{
public FlexFilter < PeopleEntity > FlexFilter { get ; } = flexFilter ;
}
var serviceCollection = new ServiceCollection ( ) ;
serviceCollection . AddSingleton < FilterExpressionBuilder < PeopleEntity > , CustomExpressionBuilder > ( ) ;
serviceCollection . AddSingleton < FlexFilterOptions < PeopleEntity > > ( ) ;
serviceCollection . AddSingleton < FlexFilter < PeopleEntity > > ( ) ;
serviceCollection . AddTransient < GenericFlexFilterService > ( ) ;
var serviceProvider = serviceCollection . BuildServiceProvider ( ) ;
var testInstance = serviceProvider . GetRequiredService < GenericFlexFilterService > ( ) ; 여기서 CustomExpressionBuilder 는 Custom Filter Expression Builder이며 FlexFilteroptions 생성자로 전달됩니다. 그런 다음 FlexFilteroptions가 FlexFilter 생성자로 전달됩니다. 마지막으로 FlexFilter는 GenericFlexFilterService 클래스에 주입됩니다.
조금 복잡해 보일지 모르지만 매우 강력합니다. Flexfetcher는 매우 유연합니다.
이전 예제에서는 엔티티에서 필드 이름을 사용했지만 사용자 정의 필드 이름을 사용할 수 있습니다. 이를 수행하는 두 가지 방법이 있습니다.
가장 간단한 방법은 필드 별칭을 문자열로 정의하는 것입니다.
// Manual creation of FlexFilter
var addressFilterOptions = new FlexFilterOptions < AddressEntity > ( ) ;
addressFilterOptions . Field ( entity => entity . City ) . Map ( "Town" ) ;
FlexFilter < AddressEntity > addressFilter = new FlexFilter < AddressEntity > ( addressFilterOptions ) ;
// Dependency injection of FlexFetcher
Services . AddSingletonFlexOptions < FlexFetcherOptions < AddressEntity > > ( options =>
{
options . Field ( entity => entity . City ) . Map ( "Town" ) ;
} ) ;
Services . AddSingleton < FlexFetcher < AddressEntity > > ( ) ;이 예에서 우리는 addressEntity.city 속성을 "타운"필드에 매핑합니다. 즉, "도시"대신 필터와 분류기에서 "타운"을 사용할 수 있습니다.
모델 클래스의 속성에서도 같은 일을 할 수 있습니다.
public class AddressModel
{
public string Town { get ; set ; }
}
// Manual creation of FlexFilter
var addressFilterOptions = new FlexFilterOptions < AddressEntity , AddressModel > ( ) ;
addressFilterOptions . Field ( entity => entity . City ) . Map ( model => model . Town ) ;
FlexFilter < AddressEntity , AddressModel > addressFilter = new FlexFilter < AddressEntity , AddressModel > ( addressFilterOptions ) ;
// Dependency injection of FlexFetcher
Services . AddSingletonFlexOptions < FlexFetcherOptions < AddressEntity , AddressModel > > ( options =>
{
options . Field ( entity => entity . City ) . Map ( model => model . Town ) ;
} ) ;
Services . AddSingleton < FlexFetcher < AddressEntity , AddressModel > > ( ) ;이 예에서는 addressEntity.city 속성을 주소 model.town 속성에 매핑합니다. 일반적으로 뷰 모델을 엔티티에 매핑하고 다른보기 모델에 대해 다른 매핑을 가질 수 있습니다.
다중 매핑이 허용되므로 하나의 엔티티 필드를 여러 별칭에 매핑 할 수 있습니다.
options . Field ( entity => entity . City ) . Map ( "Town" ) . Map ( "CityName" ) ;
모델 속성을보고 문자열 값을 동시에 매핑 할 수 있습니다.
options . Field ( x => x . City ) . Map ( model => model . Town ) . Map ( "CityName" ) ;
사용자 정의 필드에 매핑 (아래 참조)도 허용됩니다.
var customField = new PeopleFullNameCustomField ( ) ; var options = new FlexSorterOptions < PeopleEntity > ( ) ; options . AddCustomField ( customField ) . Map ( "Title" ) ; var flexSorter = new FlexSorter < PeopleEntity > ( options ) ;
이전 예에서는 엔티티의 속성 만 사용했지만 사용자 정의 표현식과 함께 사용자 정의 필드를 사용할 수 있습니다.
Flexsorters, Flexfilters, Flexfetchers에서 사용될 수 있습니다.
PeopleStity에 사용자 정의 필드 "fullName"을 추가하고 싶다고 가정 해 봅시다.
public class PeopleFullNameCustomField : BaseFlexCustomField < PeopleEntity , string > // string is a type of field
{
public override string Field => "FullName" ;
protected override Expression < Func < PeopleEntity , string > > BuildFieldExpression ( IFlexFetcherContext ? context = null )
{
return p => p . Surname + " " + p . Name ;
}
}
// Manual creation of FlexSorter
var customField = new PeopleFullNameCustomField ( ) ;
var options = new FlexSorterOptions < PeopleEntity > ( ) ;
options . AddCustomField ( customField ) . Map ( "Title" ) ;
var flexSorter = new FlexSorter < PeopleEntity > ( options ) ;
// Dependency injection of FlexFetcher
Services . AddSingletonFlexOptions < FlexFetcherOptions < PeopleEntity > > ( options =>
{
options . AddCustomField ( new PeopleFullNameCustomField ( ) ) . Map ( "Title" ) ; // Map is optional
} ) ;
Services . AddSingleton < FlexFetcher < PeopleEntity > > ( ) ; 아마도 대부분의 경우 이전 섹션에서 본 사용자 정의 필드로는 충분하지만 때로는 더 복잡한 필터 로직을 위해 필터에 사용자 정의 표현식이있는 사용자 정의 필드가 있어야합니다.
사람들이 PeopleAntity에 "PeopleGroups"를 추가하고 "Anygroup"필터를 적용한다고 가정 해 봅시다.
public class PeopleWithManyToManyGroupsCustomFilter : BaseFlexCustomFieldFilter < PeopleEntity >
{
public override string Field => "PeopleGroups" ;
protected override Expression < Func < PeopleEntity , bool > > BuildFilterExpression ( string filterOperator , object ? filterValue ,
IFlexFetcherContext ? context = null )
{
string value = ( string ) filterValue ! ;
return filterOperator switch
{
"AnyGroup" => p => p . PeopleGroups . Any ( pg => pg . Group ! . Name == value ) ,
_ => throw new NotSupportedException ( $ "Invalid filter operator: { filterOperator } " )
} ;
}
}
// Another way to create extended FlexFilter - custom class inherrited from FlexFilter
public class PeopleWithManyToManyGroups : FlexFilter < PeopleEntity >
{
public PeopleWithManyToManyGroups ( PeopleWithManyToManyGroupsCustomFilter customFilter )
{
Options . AddCustomField ( customFilter ) ;
}
}
var customFilter = new PeopleWithManyToManyGroupsCustomFilter ( ) ;
var peopleFilter = new PeopleWithManyToManyGroups ( customFilter ) ; Flexfetcher 컨텍스트는 사용자 정의 필드 및 사용자 정의 필터로 전달되는 특수 객체입니다.
사용자 정의 필드 및 사용자 정의 필터에 필요한 데이터가 포함될 수 있습니다.
문화에 따라 다른 엔티티 필드를 선택해야한다고 가정 해 봅시다.
public class CustomContext : IFlexFetcherContext // Create your own context class
{
public CultureInfo Culture { get ; set ; } = null ! ;
}
public class PeopleOriginCountryCustomField : BaseFlexCustomField < PeopleEntity , string ? >
{
public override string Field => "Country" ;
protected override Expression < Func < PeopleEntity , string ? > > BuildFieldExpression ( IFlexFetcherContext ? context = null )
{
if ( context is not CustomContext customContext )
{
throw new NotSupportedException ( "Invalid context type" ) ;
}
if ( customContext . Culture . Name == "de-DE" )
{
return entity => entity . OriginCountryDe ;
}
return entity => entity . OriginCountryEn ;
}
}
var customExpressionFilter = new PeopleOriginCountryCustomField ( ) ;
var options = new FlexFilterOptions < PeopleEntity > ( ) ;
options . AddCustomField ( customExpressionFilter ) ;
var flexFilter = new FlexFilter < PeopleEntity > ( options ) ;
var filter = new DataFilter
{
Filters = new List < DataFilter >
{
new ( )
{
Field = "Country" ,
Operator = DataFilterOperator . Equal ,
Value = "Deutschland"
}
}
} ;
var context = new CustomContext
{
Culture = new CultureInfo ( "de-DE" )
} ;
var result = flexFilter . FilterData ( _ctx . People , filter , context ) . ToList ( ) ; 이전 섹션에서는 필드에서 작업하는 방법과 매핑 방법을 보았습니다. 기본적으로 모든 필드는 표시되며 필터 및 분류기에 사용할 수 있습니다. 그러나 어떤 경우에는 필터와 분류기에 일부 필드를 숨겨야합니다.
필드를 숨길 수있는 두 가지 방법이 있습니다.
필드를 숨겨진 것으로 정의하는 방법 :
var options = new FlexFilterOptions < PeopleEntity > ( ) ;
options . Field ( x => x . CreatedByUserId ) . Hide ( ) ; // CreatedByUserId is a hidden field, it can't be used in filters and sorters
var flexFilter = new FlexFilter < PeopleEntity > ( options ) ;모든 엔티티 필드를 숨겨진 것으로 정의하는 방법 :
var options = new FlexFilterOptions < PeopleEntity > ( ) ;
options . HideOriginalFields ( ) ;
var flexFilter = new FlexFilter < PeopleEntity > ( options ) ;필드 별칭은 숨겨진 영향을받지 않으므로 원래 필드가 숨겨져 있어도 필터와 분리기에 사용할 수 있습니다.
사용자 정의 필드도 숨겨져있을 수도 있습니다.
class SimplePeopleSorterWithCustomSorter : FlexSorter < PeopleEntity >
{
public SimplePeopleSorterWithCustomSorter ( )
{
Options . AddCustomField ( new PeopleFullNameCustomField ( ) ) . Map ( "Title" ) . Hide ( ) ;
}
}HideoriginalFields ()를 사용하면 사용자 정의 필드가 자동으로 숨겨져 있지 않으므로 필요한 경우 수동으로 숨겨야합니다.
Flexfetcher는 기계 간 통신에 사용되도록 설계되었으므로 쿼리를 직렬화하고 실질화 할 수 있어야합니다.
간단한 경우 JSON 시리얼 라이저를 사용할 수 있지만 TimeOnly 유형의 필드를 사용해야하는 SOOS를 사용할 FlexFetcher.Serialization.SystemTextJson 있거나 작업자 In 사용하려면 어레이를 사용하려면 Serialize/Deserialize 배열을 사용해야합니다. FlexFetcher.Serialization.NewtonsoftJson 에서 설정 및 사용자 정의 JSON 변환기를 적용해야합니다.
FlexFetcher.Serialization.NewtonsoftJson 패키지를 설치하고 헬퍼 클래스에서 설정을 받으십시오.
var jsonSettings = NewtonsoftHelper . GetSerializerSettings ( ) ;
var json = JsonConvert . SerializeObject ( filter , jsonSettings ) ;
var deserializedFilter = JsonConvert . DeserializeObject < DataFilter > ( json , jsonSettings ) ; FlexFetcher.Serialization.SystemTextJson 패키지를 설치하고 헬퍼 클래스에서 설정을 받으십시오.
var jsonSettings = SystemTextJsonHelper . GetSerializerOptions ( ) ;
var json = JsonSerializer . Serialize ( filter , jsonSettings ) ;
var deserializedFilter = JsonSerializer . Deserialize < DataFilter > ( json , jsonSettings ) ;JSON 변환기도 다음과 같은 간결한 형식으로 JSON에서 오브 객체를 직렬화/사형화 할 수 있습니다 (DataFilter 예).
{
"L" : " And " ,
"Fs" : [
{
"O" : " Eq " ,
"F" : " Address.Town " ,
"V" : " New York "
}
]
} tests/FlexFetcherTests/SerializationTests/NewtonsoftTests.cs 및 tests/FlexFetcherTests/SerializationTests/SystemTextJsonTests.cs 및 샘플 프로젝트 samples/WebApiSample samples/WebApiSample.Framework48 에서 간결한 형식의 더 많은 예를 참조하십시오.
간결한 형식을 지원하려면 FlexFetcher.Serialization.NewtonsoftJson 및 FlexFetcher.Serialization.SystemTextJson 의 다음 변환기를 사용해야합니다.
FlexFetcherDataSorterConverterFlexFetcherDataSortersConverterFlexFetcherDataPagerConverterFlexFetcherDataFilterConverterFlexFetcherDataQueryConverter 모든 변환기에는 readOnlyShortForm 생성자 매개 변수가 있습니다. 그것이 true로 설정되면, 간결한 형식 만 사막화를 위해 허용됩니다. 그렇지 않으면 전체 및 간결한 형식이 모두 허용됩니다.
일반적으로 대부분의 경우 readOnlyShortForm 사용할 필요는 없지만, 사막화를 간결한 형식으로만 제한하려면 true로 설정할 수 있습니다.
Flexfetcher는 핵심 및 프레임 워크 인 ASP.NET 프로젝트에서 사용할 수 있지만 직렬화 제 구성은 다릅니다.
ASP.NET Core Projects (System.Text.json의 예)에서 직렬화를 구성하려면 다음 단계가 필요합니다.
FlexFetcherModelBinder 를 만듭니다FlexFetcherModelBinderProvider 를 만듭니다Program.cs 의 AddControllers 메소드에서 JSON 직렬화 설정 설정 : CS와 같은 : builder . Services . AddControllers ( options =>
{
options . ModelBinderProviders . Insert ( 0 , new FlexFetcherModelBinderProvider ( ) ) ;
} )
. AddJsonOptions ( options =>
{
options . JsonSerializerOptions . Converters . Add ( new GenericConverter ( ) ) ;
// Next converters are optional, but they are needed to support succinct format
options . JsonSerializerOptions . Converters . Add ( new FlexFetcherDataSorterConverter ( ) ) ;
options . JsonSerializerOptions . Converters . Add ( new FlexFetcherDataSortersConverter ( ) ) ;
options . JsonSerializerOptions . Converters . Add ( new FlexFetcherDataPagerConverter ( ) ) ;
options . JsonSerializerOptions . Converters . Add ( new FlexFetcherDataFilterConverter ( ) ) ;
options . JsonSerializerOptions . Converters . Add ( new FlexFetcherDataQueryConverter ( ) ) ;
} ) ; samples/WebApiSample 의 코드를 참조하십시오.
ASP.NET 프레임 워크 프로젝트에서 직렬화를 구성하려면 다음 단계가 필요합니다 (NewTonsoft.json의 예) :
FlexFetcherModelBinder 를 만듭니다FlexFetcherModelBinderProvider 를 만듭니다WebApiConfig.cs 에서 JSON 직렬화 설정 설정 : var jsonSettings = NewtonsoftHelper . GetSerializerSettings ( ) ;
config . Formatters . JsonFormatter . SerializerSettings = jsonSettings ;
// Next converters are optional, but they are needed to support succinct format
config . Formatters . JsonFormatter . SerializerSettings . Converters . Add ( new FlexFetcherDataFilterConverter ( ) ) ;
config . Formatters . JsonFormatter . SerializerSettings . Converters . Add ( new FlexFetcherDataSortersConverter ( ) ) ;
config . Formatters . JsonFormatter . SerializerSettings . Converters . Add ( new FlexFetcherDataSorterConverter ( ) ) ;
config . Formatters . JsonFormatter . SerializerSettings . Converters . Add ( new FlexFetcherDataPagerConverter ( ) ) ;
config . Formatters . JsonFormatter . SerializerSettings . Converters . Add ( new FlexFetcherDataQueryConverter ( ) ) ;
config . Services . Insert ( typeof ( ModelBinderProvider ) , 0 , new FlexFetcherModelBinderProvider ( ) ) ; samples/WebApiSample.Framework48 의 코드를 참조하십시오.
저장소에는 두 가지 샘플 프로젝트가 있습니다.
samples/WebApiSample -ASP.NET Core Web API 프로젝트samples/WebApiSample.Framework48 -ASP.NET 프레임 워크 4.8 웹 API 프로젝트두 프로젝트 모두 동일한 기능을 가지고 있으며 ASP.NET 프로젝트에서 FlexFetcher를 사용하는 방법을 보여줍니다.
Flexfetcher가 실제 프로젝트에서 어떻게 작동하는지 확인하기 위해 구축하고 실행하십시오. 좋아하는 REST 클라이언트를 사용하여 API에 요청을 보냅니다. 요청의 예는 samples/WebApiSample/ReadMe.md 및 samples/WebApiSample.Framework48/ReadMe.md 에서 찾을 수 있습니다.
또한 tests/FlexFetcherTests 폴더에는 다양한 시나리오에서 FlexFetcher를 사용하는 방법을 보여주는 테스트가 있습니다.