在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称(OpenSource Name):Husqvik/GraphQlClientGenerator开源软件地址(OpenSource Url):https://github.com/Husqvik/GraphQlClientGenerator开源编程语言(OpenSource Language):C# 100.0%开源软件介绍(OpenSource Introduction):GraphQL C# client generatorThis simple console app generates C# GraphQL query builder and data classes for simple, compiler checked, usage of a GraphQL API. Generator app usageGraphQlClientGenerator.Console --serviceUrl <GraphQlServiceUrl> --outputPath <TargetPath> --namespace <TargetNamespace> [--header <header value>] Nuget packageInstallation: Install-Package GraphQlClientGenerator dotnet tooldotnet tool install GraphQlClientGenerator.Tool --global
graphql-client-generator --serviceUrl <GraphQlServiceUrl> --outputPath <TargetPath> --namespace <TargetNamespace> [--header <header value>] CodeCode example for class generation: var schema = await GraphQlGenerator.RetrieveSchema(url);
var generator = new GraphQlGenerator();
var generatedClasses = generator.Generate(schema); or var schema = await GraphQlGenerator.RetrieveSchema(url);
var csharpCode = new GraphQlGenerator().GenerateFullClientCSharpFile(schema, "MyGqlApiClient");
await File.WriteAllTextAsync("MyGqlApiClient.cs", csharpCode); C# 9 source generatorC# 9 introduced source generators that can be attached to compilation process. Generated classes will be automatically included in project. Project file example: <PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<!-- GraphQL generator properties -->
<GraphQlClientGenerator_ServiceUrl>https://api.tibber.com/v1-beta/gql</GraphQlClientGenerator_ServiceUrl>
<!-- GraphQlClientGenerator_Namespace is optional; if omitted the first compilation unit namespace will be used -->
<GraphQlClientGenerator_Namespace>$(RootNamespace)</GraphQlClientGenerator_Namespace>
<GraphQlClientGenerator_CustomClassMapping>Consumption:ConsumptionEntry|Production:ProductionEntry|RootMutation:TibberMutation|Query:Tibber</GraphQlClientGenerator_CustomClassMapping>
<!-- other GraphQL generator property values -->
</PropertyGroup>
<ItemGroup>
<PackageReference Include="GraphQlClientGenerator" Version="0.9.*" IncludeAssets="analyzers" />
<!-- AdditionalFiles and GraphQlClientGenerator_ServiceUrl are mutually exclusive -->
<!-- <AdditionalFiles Include="GqlSchemaTibberApi.gql.schema.json" CacheObjects="true" /> --> <!-- schema file name must end with ".gql.schema.json" -->
<CompilerVisibleProperty Include="GraphQlClientGenerator_ServiceUrl" />
<CompilerVisibleProperty Include="GraphQlClientGenerator_Namespace" />
<!-- other configuration properties -->
<!--<CompilerVisibleProperty Include="GraphQlClientGenerator_{ConfigurationProperty}" />-->
</ItemGroup> Query builder usagevar builder =
new QueryQueryBuilder()
.WithMe(
new MeQueryBuilder()
.WithAllScalarFields()
.WithHome(
new HomeQueryBuilder()
.WithAllScalarFields()
.WithSubscription(
new SubscriptionQueryBuilder()
.WithStatus()
.WithValidFrom())
.WithSignupStatus(
new SignupStatusQueryBuilder().WithAllFields())
.WithDisaggregation(
new DisaggregationQueryBuilder().WithAllFields()),
"b420001d-189b-44c0-a3d5-d62452bfdd42")
.WithEnergyStatements ("2016-06", "2016-10"));
var query = builder.Build(Formatting.Indented); results into query {
me {
id
firstName
lastName
fullName
ssn
email
language
tone
home (id: "b420001d-189b-44c0-a3d5-d62452bfdd42") {
id
avatar
timeZone
subscription {
status
validFrom
}
signupStatus {
registrationStartedTimestamp
registrationCompleted
registrationCompletedTimestamp
checkCurrentSupplierPassed
supplierSwitchConfirmationPassed
startDatePassed
firstReadingReceived
firstBillingDone
firstBillingTimestamp
}
disaggregation {
year
month
fixedConsumptionKwh
fixedConsumptionKwhPercent
heatingConsumptionKwh
heatingConsumptionKwhPercent
behaviorConsumptionKwh
behaviorConsumptionKwhPercent
}
}
energyStatements(from: "2016-06", to: "2016-10")
}
} Mutationvar mutation =
new MutationQueryBuilder()
.WithUpdateHome(
new HomeQueryBuilder().WithAllScalarFields(),
new UpdateHomeInput { HomeId = Guid.Empty, AppNickname = "My nickname", Type = HomeType.House, NumberOfResidents = 4, Size = 160, AppAvatar = HomeAvatar.Floorhouse1, PrimaryHeatingSource = HeatingSource.Electricity }
)
.Build(Formatting.Indented, 2); result: mutation {
updateHome (input: {
homeId: "00000000-0000-0000-0000-000000000000"
appNickname: "My nickname"
appAvatar: FLOORHOUSE1
size: 160
type: HOUSE
numberOfResidents: 4
primaryHeatingSource: ELECTRICITY
}) {
id
timeZone
appNickname
appAvatar
size
type
numberOfResidents
primaryHeatingSource
hasVentilationSystem
}
} Field exclusionSometimes there is a need to select almost all fields of a queried object except few. In that case new ViewerQueryBuilder()
.WithHomes(
new HomeQueryBuilder()
.WithAllScalarFields()
.ExceptPrimaryHeatingSource()
.ExceptMainFuseSize()
)
.Build(Formatting.Indented); result: query {
homes {
id
timeZone
appNickname
appAvatar
size
type
numberOfResidents
hasVentilationSystem
}
}
AliasesQueried fields can be freely renamed to match target data classes using GraphQL aliases. new ViewerQueryBuilder("MyQuery")
.WithHome(
new HomeQueryBuilder()
.WithType()
.WithSize()
.WithAddress(new AddressQueryBuilder().WithAddress1("primaryAddressText").WithCountry(), "primaryAddress"),
Guid.NewGuid(),
"primaryHome")
.WithHome(
new HomeQueryBuilder()
.WithType()
.WithSize()
.WithAddress(new AddressQueryBuilder().WithAddress1("secondaryAddressText").WithCountry(), "secondaryAddress"),
Guid.NewGuid(),
"secondaryHome")
.Build(Formatting.Indented); result: query MyQuery {
primaryHome: home (id: "120efe4a-6839-45fc-beed-27455d29212f") {
type
size
primaryAddress: address {
primaryAddressText: address1
country
}
}
secondaryHome: home (id: "0c735830-be56-4a3d-a8cb-d0189037f221") {
type
size
secondaryAddress: address {
secondaryAddressText: address1
country
}
}
} Query parametersvar homeIdParameter = new GraphQlQueryParameter<Guid>("homeId", "ID", homeId);
var builder =
new TibberQueryBuilder()
.WithViewer(
new ViewerQueryBuilder()
.WithHome(new HomeQueryBuilder().WithAllScalarFields(), homeIdParameter)
)
.WithParameter(homeIdParameter); result: query ($homeId: ID = "c70dcbe5-4485-4821-933d-a8a86452737b") {
viewer{
home(id: $homeId) {
id
timeZone
appNickname
appAvatar
size
type
numberOfResidents
primaryHeatingSource
hasVentilationSystem
mainFuseSize
}
}
} Directivesvar includeDirectParameter = new GraphQlQueryParameter<bool>("direct", "Boolean", true);
var includeDirective = new IncludeDirective(includeDirectParameter);
var skipDirective = new SkipDirective(true);
var builder =
new TibberQueryBuilder()
.WithViewer(
new ViewerQueryBuilder()
.WithName(include: includeDirective)
.WithAccountType(skip: skipDirective)
.WithHomes(new HomeQueryBuilder().WithId(), skip: skipDirective)
)
.WithParameter(includeDirectParameter); result: query (
$direct: Boolean = true) {
viewer {
name @include(if: $direct)
accountType @skip(if: true)
homes @skip(if: true) {
id
}
}
} Inline fragmentsvar builder =
new RootQueryBuilder("InlineFragments")
.WithUnion(
new UnionTypeQueryBuilder()
.WithTypeName()
.WithConcreteType1Fragment(new ConcreteType1QueryBuilder().WithAllFields())
.WithConcreteType2Fragment(new ConcreteType2QueryBuilder().WithAllFields())
.WithConcreteType3Fragment(
new ConcreteType3QueryBuilder()
.WithTypeName()
.WithName()
.WithConcreteType3Field("alias")
.WithFunction("my value", "myResult1")
)
)
.WithInterface(
new NamedTypeQueryBuilder()
.WithName()
.WithConcreteType3Fragment(
new ConcreteType3QueryBuilder()
.WithTypeName()
.WithName()
.WithConcreteType3Field()
.WithFunction("my value")
),
Guid.Empty
); result: query InlineFragments {
union {
__typename
... on ConcreteType1 {
name
concreteType1Field
}
... on ConcreteType2 {
name
concreteType2Field
}
... on ConcreteType3 {
__typename
name
alias: concreteType3Field
myResult1: function(value: "my value")
}
}
interface(parameter: "00000000-0000-0000-0000-000000000000") {
name
... on ConcreteType3 {
__typename
name
concreteType3Field
function(value: "my value")
}
}
} Custom scalar typesGraphQL supports custom scalar types. By default these are mapped to var configuration = new GraphQlGeneratorConfiguration();
configuration.ScalarFieldTypeMappingProvider = new MyCustomScalarFieldTypeMappingProvider();
public class MyCustomScalarFieldTypeMappingProvider : IScalarFieldTypeMappingProvider
{
public ScalarFieldTypeDescription GetCustomScalarFieldType(GraphQlGeneratorConfiguration configuration, GraphQlType baseType, GraphQlTypeBase valueType, string valueName)
{
valueType = valueType is GraphQlFieldType fieldType ? fieldType.UnwrapIfNonNull() : valueType;
// DateTime and Byte
switch (valueType.Name)
{
case "Byte": return new ScalarFieldTypeDescription { NetTypeName = "byte?", FormatMask = null };
case "DateTime": return new ScalarFieldTypeDescription { NetTypeName = "DateTime?", FormatMask = null };
}
// fallback - not needed if all fields and arguments are resolved or the expected type is of "object" type
return DefaultScalarFieldTypeMappingProvider.GetFallbackFieldType(configuration, valueType);
}
} Generated class example: public class OrderType
{
public DateTime? CreatedDateTimeUtc { get; set; }
public byte? SomeSmallNumber { get; set; }
} vs. public class OrderType
{
public object CreatedDateTimeUtc { get; set; }
public object SomeSmallNumber { get; set; }
} C# 9 source generator custom typesSource generator supports [
{
"patternBaseType": ".+",
"patternValueType": ".+",
"patternValueName": "^((timestamp)|(.*(f|F)rom)|(.*(t|T)o))$",
"netTypeName": "DateTimeOffset?",
"formatMask": "O"
}
] All pattern values must be specified. The file must be named <ItemGroup>
<AdditionalFiles Include="RegexScalarFieldTypeMappingProvider.gql.config.json" CacheObjects="true" />
</ItemGroup> |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论