Skip to content

Don't use runtime reflection to read from data models (use source generation or IL code instead) #695

Description

@ivarne

Description

Runtime reflection is known to be very slow, and with validation we use lots of it to be able to read properties of dynamic objects. Generated code that looks like this would be way faster

public class FieldAccessor<T>
{
    public object? GetValue(T root, string path, int[] indexes)
    {
        return path switch
        {
            "name" => root.Name,
            "children.name" => root.Children?[indexes[0]]?.Name,
            ///...
        }
    }
    
    public void SetValue(T root, object? value, string path, int[] indexes)
    {...}
}

Additional Information

There are two common patterns to generate code in C#

Source Generation

  • Pro
    • Actual source code is generated, which might make debugging easer, as it is possible to see the generated code while debugging.
    • Errors can be detected and notified at compile time.
    • Most performant, as it does not add to startup time.
  • Con
    • Tooling support not always the best.

IL generated code

  • Pro
    • Fully runtime solution, no dependencies on build
  • Con
    • First run will be slower in a new server app instance.
    • Harder to debug (no source will be available), but how likely are there to be issues in an auto generated property accessor.

Tasks

  • select SourceGenerator or IL generator
  • write a method that uses reflection/sg equivalent to get a list of all json style accessors for all properties to use in the switch/case (respecting [JsonPropertyName], and supporting recursive types)
  • Add the generated code
  • Use the new field accessors everywhere.

Acceptance Criterias

Use Source generation or cached IL generated code to access properties in data models using strings.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    • Status
      No status

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions