-
-
Notifications
You must be signed in to change notification settings - Fork 8.6k
[dotnet] Enable Option<T> to work when no value is provided #16648
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: trunk
Are you sure you want to change the base?
Changes from all commits
f976e2c
82c9f91
70b4e44
875b0c1
c28d925
003d88f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| // <copyright file="OptionalConverterFactory.cs" company="Selenium Committers"> | ||
| // Licensed to the Software Freedom Conservancy (SFC) under one | ||
| // or more contributor license agreements. See the NOTICE file | ||
| // distributed with this work for additional information | ||
| // regarding copyright ownership. The SFC licenses this file | ||
| // to you under the Apache License, Version 2.0 (the | ||
| // "License"); you may not use this file except in compliance | ||
| // with the License. You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, | ||
| // software distributed under the License is distributed on an | ||
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| // KIND, either express or implied. See the License for the | ||
| // specific language governing permissions and limitations | ||
| // under the License. | ||
| // </copyright> | ||
|
|
||
| using System; | ||
| using System.Text.Json; | ||
| using System.Text.Json.Serialization; | ||
| using System.Text.Json.Serialization.Metadata; | ||
|
|
||
| namespace OpenQA.Selenium.BiDi.Json.Converters; | ||
|
|
||
| internal sealed class OptionalConverterFactory : JsonConverterFactory | ||
| { | ||
| public override bool CanConvert(Type typeToConvert) => typeToConvert.IsGenericType && typeToConvert.GetGenericTypeDefinition() == typeof(Optional<>); | ||
|
|
||
| public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options) | ||
| { | ||
| var converter = (JsonConverter?)Activator.CreateInstance(typeof(OptionalConverter<>).MakeGenericType(typeToConvert.GenericTypeArguments[0])); | ||
|
|
||
| return converter; | ||
| } | ||
|
|
||
| internal sealed class OptionalConverter<T> : JsonConverter<Optional<T>> | ||
| { | ||
| public override bool HandleNull => true; | ||
|
|
||
| public override Optional<T> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) | ||
| { | ||
| var converter = (JsonTypeInfo<T>)options.GetTypeInfo(typeof(T)); | ||
|
|
||
| T? value = JsonSerializer.Deserialize<T>(ref reader, converter); | ||
| return new Optional<T>(value); | ||
| } | ||
|
|
||
| public override void Write(Utf8JsonWriter writer, Optional<T> value, JsonSerializerOptions options) | ||
| { | ||
| if (value.TryGetValue(out var optionalValue)) | ||
| { | ||
| var converter = (JsonTypeInfo<T?>)options.GetTypeInfo(typeof(T?)); | ||
|
|
||
| JsonSerializer.Serialize(writer, optionalValue, converter); | ||
| } | ||
| else | ||
| { | ||
| throw new JsonException("This property should be annotated with [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]"); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -316,7 +316,7 @@ public async Task CanSetViewport() | |
| Assert.That(await GetHeightAsync(), Is.EqualTo(300)); | ||
|
|
||
| await context.SetViewportAsync(new() { Viewport = new Viewport(250, 300) }); | ||
| await context.SetViewportAsync(new() { Viewport = default }); // Sends nothing | ||
| await context.SetViewportAsync(new() { Viewport = Optional<Viewport?>.None }); // Sends nothing | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What if
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. True, I didn't introduce this helper in initial implementation. I propose just to cover |
||
|
|
||
| Assert.That(await GetWidthAsync(), Is.EqualTo(250)); | ||
| Assert.That(await GetHeightAsync(), Is.EqualTo(300)); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought it was better for AOT, like
StringEnumConverterwhere we specify this attribute with explicitly mentioning type (Viewportin this case). Additionally if we recall modules cross-referencing, I like the approach: explicitly specify converters.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I forgot about AOT, honestly. We should really enable AOT analyzers to we have visibility on AOT-unfriendly things.
selenium/dotnet/src/webdriver/Selenium.WebDriver.csproj
Lines 49 to 54 in b446e16
But either way, this convertor is nothing more than a reminder: all the logic is in
[JsonIgnore(WhenWritingDefault)].I asked the .NET devs if there's a nice way of doing this dotnet/runtime#122049