Skip to content

Reduce record usage in published projects #48907

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

Merged
merged 31 commits into from
Jul 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
bd3ca9d
Convert CollectionModelBinder to class
david-acker Jun 18, 2023
b50f5a6
Convert AltSvcHeader to class
david-acker Jun 18, 2023
6f40f74
Convert InternalHeader to class
david-acker Jun 18, 2023
f331a08
Convert OnRegistrationClose to struct
david-acker Jun 18, 2023
923930d
Convert UnacknowledgedRenderBatch to class
david-acker Jun 19, 2023
1967540
Convert OptionsRecord to struct
david-acker Jun 19, 2023
7d44f3a
Convert BrowserOptions to class
david-acker Jun 19, 2023
2073db0
Convert LogEntry to class
david-acker Jun 19, 2023
94f0d01
Convert BodyDescriptorInfo to class
david-acker Jun 19, 2023
b5cc7ee
Convert RouteParameter to class
david-acker Jun 19, 2023
b9bec97
Convert InternalAccessTokenResult to struct
david-acker Jun 19, 2023
d075af9
Clean up spacing
david-acker Jun 20, 2023
188177a
Convert DfaBuilderWorkerWorkItem to struct
david-acker Jun 20, 2023
8d89d8d
Fix property names
david-acker Jun 20, 2023
94f9d51
Set properties to init
david-acker Jun 20, 2023
ae3478f
Clean up
david-acker Jun 20, 2023
5cd5788
Convert ComponentTypeInfoCacheEntry to class
david-acker Jun 21, 2023
384164c
Convert FormDataConverterReadParameters to class
david-acker Jun 21, 2023
5cfb980
Convert ComponentIdAndDepth to struct
david-acker Jun 21, 2023
eeee9c9
Convert MethodInfoData to struct
david-acker Jun 21, 2023
3cb6eaa
Convert BrowserTab to class
david-acker Jun 21, 2023
e67bb69
Revert unrelated changes
david-acker Jun 21, 2023
d56ac8e
Convert NamedEvent to struct
david-acker Jun 22, 2023
288b841
Merge main
david-acker Jun 22, 2023
8841a6d
Revert submodule changes
david-acker Jun 22, 2023
15aee55
Merge branch 'main' into reduce-record-usage
david-acker Jun 30, 2023
8446029
Add Deconstruct to ComponentTypeInfoCacheEntry
david-acker Jul 1, 2023
dffaa71
Merge remote-tracking branch 'origin/main' into reduce-record-usage
david-acker Jul 7, 2023
2f2fd2a
Seal InternalHeader
david-acker Jul 11, 2023
c6e4900
Merge remote-tracking branch 'origin/main' into reduce-record-usage
david-acker Jul 21, 2023
07d4abb
Convert FormDataConverterReadParameters to struct
david-acker Jul 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 22 additions & 3 deletions src/Components/Components/src/ComponentFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,26 @@ void Initialize(IServiceProvider serviceProvider, IComponent component)
}

// Tracks information about a specific component type that ComponentFactory uses
private record class ComponentTypeInfoCacheEntry(
IComponentRenderMode? ComponentTypeRenderMode,
Action<IServiceProvider, IComponent> PerformPropertyInjection);
private sealed class ComponentTypeInfoCacheEntry
{
public IComponentRenderMode? ComponentTypeRenderMode { get; }

public Action<IServiceProvider, IComponent> PerformPropertyInjection { get; }

public ComponentTypeInfoCacheEntry(
IComponentRenderMode? componentTypeRenderMode,
Action<IServiceProvider, IComponent> performPropertyInjection)
{
ComponentTypeRenderMode = componentTypeRenderMode;
PerformPropertyInjection = performPropertyInjection;
}

public void Deconstruct(
out IComponentRenderMode? componentTypeRenderMode,
out Action<IServiceProvider, IComponent> performPropertyInjection)
{
componentTypeRenderMode = ComponentTypeRenderMode;
performPropertyInjection = PerformPropertyInjection;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -576,10 +576,44 @@ private static FormDataConverterReadParameters CreateFormDataConverterParameters
Expression.Parameter(typeof(bool).MakeByRefType(), "foundValue"));
}

private record struct FormDataConverterReadParameters(
ParameterExpression ReaderParam,
ParameterExpression TypeParam,
ParameterExpression OptionsParam,
ParameterExpression ResultParam,
ParameterExpression FoundValueParam);
private readonly struct FormDataConverterReadParameters
{
public ParameterExpression ReaderParam { get; }

public ParameterExpression TypeParam { get; }

public ParameterExpression OptionsParam { get; }

public ParameterExpression ResultParam { get; }

public ParameterExpression FoundValueParam { get; }

public FormDataConverterReadParameters(
ParameterExpression readerParam,
ParameterExpression typeParam,
ParameterExpression optionsParam,
ParameterExpression resultParam,
ParameterExpression foundValueParam)
{
ReaderParam = readerParam;
TypeParam = typeParam;
OptionsParam = optionsParam;
ResultParam = resultParam;
FoundValueParam = foundValueParam;
}

public void Deconstruct(
out ParameterExpression readerParam,
out ParameterExpression typeParam,
out ParameterExpression optionsParam,
out ParameterExpression resultParam,
out ParameterExpression foundValueParam)
{
readerParam = ReaderParam;
typeParam = TypeParam;
optionsParam = OptionsParam;
resultParam = ResultParam;
foundValueParam = FoundValueParam;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,29 @@ private void WriteComponentHtml(int componentId, TextWriter output, bool allowBo
}
}

private readonly record struct ComponentIdAndDepth(int ComponentId, int Depth);
private readonly record struct SequenceAndKey(int Sequence, object? Key);
private readonly struct ComponentIdAndDepth
{
public int ComponentId { get; }

public int Depth { get; }

public ComponentIdAndDepth(int componentId, int depth)
{
ComponentId = componentId;
Depth = depth;
}
}

private readonly struct SequenceAndKey
{
public int Sequence { get; }

public object? Key { get; }

public SequenceAndKey(int sequence, object? key)
{
Sequence = sequence;
Key = key;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -160,34 +160,34 @@ static MethodInfoData GetMethodInfoData(MethodInfo methodInfo)
var declaringType = methodInfo.DeclaringType;
if (declaringType is null)
{
return new(IsSingleArgumentIndexer: false);
return new(isSingleArgumentIndexer: false);
}

// Check whether GetDefaultMembers() (if present in CoreCLR) would return a member of this type. Compiler
// names the indexer property, if any, in a generated [DefaultMember] attribute for the containing type.
var defaultMember = declaringType.GetCustomAttribute<DefaultMemberAttribute>(inherit: true);
if (defaultMember is null)
{
return new(IsSingleArgumentIndexer: false);
return new(isSingleArgumentIndexer: false);
}

// Find default property (the indexer) and confirm its getter is the method in this expression.
var runtimeProperties = declaringType.GetRuntimeProperties();
if (runtimeProperties is null)
{
return new(IsSingleArgumentIndexer: false);
return new(isSingleArgumentIndexer: false);
}

foreach (var property in runtimeProperties)
{
if (string.Equals(defaultMember.MemberName, property.Name, StringComparison.Ordinal) &&
property.GetMethod == methodInfo)
{
return new(IsSingleArgumentIndexer: true);
return new(isSingleArgumentIndexer: true);
}
}

return new(IsSingleArgumentIndexer: false);
return new(isSingleArgumentIndexer: false);
}
}

Expand Down Expand Up @@ -297,5 +297,13 @@ private static void FormatConstantValue(ConstantExpression constantExpression, r
}
}

private record struct MethodInfoData(bool IsSingleArgumentIndexer);
private readonly struct MethodInfoData
{
public bool IsSingleArgumentIndexer { get; }

public MethodInfoData(bool isSingleArgumentIndexer)
{
IsSingleArgumentIndexer = isSingleArgumentIndexer;
}
}
}
34 changes: 25 additions & 9 deletions src/Components/WebAssembly/Server/src/TargetPickerUi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -425,13 +425,29 @@ private async Task<IEnumerable<BrowserTab>> GetOpenedBrowserTabs()
return JsonSerializer.Deserialize<BrowserTab[]>(jsonResponse, JsonOptions)!;
}

private sealed record BrowserTab
(
string Id,
string Type,
string Url,
string Title,
string DevtoolsFrontendUrl,
string WebSocketDebuggerUrl
);
private sealed class BrowserTab
{
public string Id { get; }
public string Type { get; }
public string Url { get; }
public string Title { get; }
public string DevtoolsFrontendUrl { get; }
public string WebSocketDebuggerUrl { get; }

public BrowserTab(
string id,
string type,
string url,
string title,
string devtoolsFrontendUrl,
string webSocketDebuggerUrl)
{
Id = id;
Type = type;
Url = url;
Title = title;
DevtoolsFrontendUrl = devtoolsFrontendUrl;
WebSocketDebuggerUrl = webSocketDebuggerUrl;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,32 @@ public override void Write(Utf8JsonWriter writer, InteractiveRequestOptions valu
InteractiveRequestOptionsSerializerContext.Default.OptionsRecord);
}

internal record struct OptionsRecord(
[property: JsonInclude] string ReturnUrl,
[property: JsonInclude] IEnumerable<string> Scopes,
[property: JsonInclude] InteractionType Interaction,
[property: JsonInclude] Dictionary<string, object>? AdditionalRequestParameters);
internal readonly struct OptionsRecord
{
[JsonInclude]
public string ReturnUrl { get; init; }

[JsonInclude]
public IEnumerable<string> Scopes { get; init; }

[JsonInclude]
public InteractionType Interaction { get; init; }

[JsonInclude]
public Dictionary<string, object>? AdditionalRequestParameters { get; init; }

public OptionsRecord(
string returnUrl,
IEnumerable<string> scopes,
InteractionType interaction,
Dictionary<string, object>? additionalRequestParameters)
{
ReturnUrl = returnUrl;
Scopes = scopes;
Interaction = interaction;
AdditionalRequestParameters = additionalRequestParameters;
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,4 +255,16 @@ internal class RemoteAuthenticationServiceJavaScriptLoggingOptions
}

// Internal for testing purposes
internal record struct InternalAccessTokenResult([property: JsonConverter(typeof(JsonStringEnumConverter<AccessTokenResultStatus>))] AccessTokenResultStatus Status, AccessToken Token);
internal readonly struct InternalAccessTokenResult
{
[JsonConverter(typeof(JsonStringEnumConverter<AccessTokenResultStatus>))]
public AccessTokenResultStatus Status { get; init; }

public AccessToken Token { get; init; }

public InternalAccessTokenResult(AccessTokenResultStatus status, AccessToken token)
{
Status = status;
Token = token;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,10 @@ public void NotifyRenderCompleted(long batchId)
nextUnacknowledgedBatch.CompletionSource.SetResult();
}

private sealed record UnacknowledgedRenderBatch
private sealed class UnacknowledgedRenderBatch
{
public long BatchId { get; init; }

public TaskCompletionSource CompletionSource { get; init; }
}
}
60 changes: 47 additions & 13 deletions src/Grpc/JsonTranscoding/src/Shared/ServiceDescriptorHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -428,11 +428,11 @@ public static Dictionary<string, RouteParameter> ResolveRouteParameterDescriptor
{
// A repeating field isn't a message type. The JSON parser will parse using the containing
// type to get the repeating collection.
return new BodyDescriptorInfo(responseBodyDescriptor.ContainingType, responseBodyDescriptor, IsDescriptorRepeated: true, propertyInfo);
return new BodyDescriptorInfo(responseBodyDescriptor.ContainingType, responseBodyDescriptor, isDescriptorRepeated: true, propertyInfo);
}
else
{
return new BodyDescriptorInfo(responseBodyDescriptor.MessageType, responseBodyDescriptor, IsDescriptorRepeated: false, propertyInfo);
return new BodyDescriptorInfo(responseBodyDescriptor.MessageType, responseBodyDescriptor, isDescriptorRepeated: false, propertyInfo);
}
}
else
Expand All @@ -444,7 +444,7 @@ public static Dictionary<string, RouteParameter> ResolveRouteParameterDescriptor
requestParameter = methodInfo.GetParameters().SingleOrDefault(p => p.Name == "request");
}

return new BodyDescriptorInfo(methodDescriptor.InputType, FieldDescriptor: null, IsDescriptorRepeated: false, ParameterInfo: requestParameter);
return new BodyDescriptorInfo(methodDescriptor.InputType, fieldDescriptor: null, isDescriptorRepeated: false, parameterInfo: requestParameter);
}
}

Expand Down Expand Up @@ -562,12 +562,32 @@ private static bool IsCustomType(MessageDescriptor messageDescriptor)
return false;
}

public sealed record BodyDescriptorInfo(
MessageDescriptor Descriptor,
FieldDescriptor? FieldDescriptor,
bool IsDescriptorRepeated,
PropertyInfo? PropertyInfo = null,
ParameterInfo? ParameterInfo = null);
public sealed class BodyDescriptorInfo
{
public MessageDescriptor Descriptor { get; }

public FieldDescriptor? FieldDescriptor { get; }

public bool IsDescriptorRepeated { get; }

public PropertyInfo? PropertyInfo { get; }

public ParameterInfo? ParameterInfo { get; }

public BodyDescriptorInfo(
MessageDescriptor descriptor,
FieldDescriptor? fieldDescriptor,
bool isDescriptorRepeated,
PropertyInfo? propertyInfo = null,
ParameterInfo? parameterInfo = null)
{
Descriptor = descriptor;
FieldDescriptor = fieldDescriptor;
IsDescriptorRepeated = isDescriptorRepeated;
PropertyInfo = propertyInfo;
ParameterInfo = parameterInfo;
}
}

public static string FormatUnderscoreName(string input, bool pascalCase, bool preservePeriod)
{
Expand Down Expand Up @@ -626,7 +646,21 @@ public static string FormatUnderscoreName(string input, bool pascalCase, bool pr
}
}

internal record RouteParameter(
List<FieldDescriptor> DescriptorsPath,
HttpRouteVariable RouteVariable,
string JsonPath);
internal sealed class RouteParameter
{
public List<FieldDescriptor> DescriptorsPath { get; }

public HttpRouteVariable RouteVariable { get; }

public string JsonPath { get; }

public RouteParameter(
List<FieldDescriptor> descriptorsPath,
HttpRouteVariable routeVariable,
string jsonPath)
{
DescriptorsPath = descriptorsPath;
RouteVariable = routeVariable;
JsonPath = jsonPath;
}
}
23 changes: 22 additions & 1 deletion src/Http/Routing/src/Matching/DfaMatcherBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -987,5 +987,26 @@ private static bool TryGetRequiredValue(RoutePattern routePattern, RoutePatternP
return !RouteValueEqualityComparer.Default.Equals(value, string.Empty);
}

private readonly record struct DfaBuilderWorkerWorkItem(RouteEndpoint Endpoint, int PrecedenceDigit, List<DfaNode> Parents);
public readonly struct DfaBuilderWorkerWorkItem
{
public RouteEndpoint Endpoint { get; }

public int PrecedenceDigit { get; }

public List<DfaNode> Parents { get; }

public DfaBuilderWorkerWorkItem(RouteEndpoint endpoint, int precedenceDigit, List<DfaNode> parents)
{
Endpoint = endpoint;
PrecedenceDigit = precedenceDigit;
Parents = parents;
}

public void Deconstruct(out RouteEndpoint endpoint, out int precedenceDigit, out List<DfaNode> parents)
{
endpoint = Endpoint;
precedenceDigit = PrecedenceDigit;
parents = Parents;
}
}
}
Loading