Avalonia: [Discussion] [DevTools] [Spec] DevTool Settings Roslyn Source Generator

Created on 1 Oct 2020  路  6Comments  路  Source: AvaloniaUI/Avalonia

DevTool Settings Roslyn Source Generator

Hi,
I've done various tests on how to manage the DevTool configuration.
But before I start investing time in development, I'd like to hear from you.

I would like to use Roslyn Source Generator.

I would like to create the following structure:

  • Avalonia.Diagnostics.Settings.Generators
  • Avalonia.Diagnostics.Common
  • Avalonia.Diagnostics.Settings.Generators.Xml
  • Avalonia.Diagnostics.Settings.Xml
  • ec..

Avalonia.Diagnostics.Settings.Generators

It is a code analyzer that generates DevToolsOptions based and a file describing its structure

Avalonia.Diagnostics.Common

dependencies: Avalonia.Diagnostics.Generators(only in build)
contents:

  • DevToolsOptions.yaml
  • DevToolsOptions.cs
  • DevToolsOptions.Generated.cs
  • IDevToolOptionsStoreProvider
  • IDevTool

DevToolsOptions.yaml

this is the file that contains the DevToolsOptions structure which will then be expanded into DevToolsOptions.Generated.cs.
I thought about YAML because it is easy to read and not very verbose.

example of possible file:

Version: "1.0.0.0" #Type:System.Verison
Window:
  StartupLocation: "CenterScreen" #Type:Avalonia.Controls.WindowStartupLocation
  State: "Normal" #Type:Avalonia.Controls.WindowState
  Position: null #Type:Avalonia.PixelPoint?
Console:
  IsVisible: false #Type:System.Boolean
  Height: NaN #Type:System.Double
ShouldVisualizeMarginPadding: true #Type:System.Boolean
ShouldVisualizeDirtyRects: false #Type:System.Boolean
ShowFpsOverlay: false #Type:System.Boolean
FavoritesProperties:
  - FavoriteProperties:
    Name: "All" #Type:System.String
  - FavoriteProperties:
    Name: "Layout"
    Properties: #Type:System.String[]
      - Item: "Bounds"
      - Item: "Clips"
      - Item: "Height"

Directives:

  • # Type indicates the type of property, if not provided treat it as a new object; example: Console will create a class named ConsoleSettings
  • ? after the type name indicates that it is a null type
  • [] after the type name indicates that it is an array

DevToolsOptions.cs

the partial class is used to not report an error in the intellisense when DevToolsOptions has not yet been generated.

public partial class DevToolsOptions
{
}

IDevToolsOptionsStoreProvider.cs

defines the interface for loading or saving the configuration

public interface IDevToolsOptionsStoreProvider
{
   void Load(DevToolsOptions options);
   Task Save(DevToolsOptions options); // it is asynchronous because saving can take a long time
}

IDevTool.cs

defines the interface returned by the AttachDevTools extension method and allows configuration of additional options

public interface IDevTool
{
   IDevTool With(DevToolsOptions options);
   IDevTool With(IDevToolsOptionsStoreProvider storeProvider);
}

Avalonia.Diagnostics.Settings.Generators.Xml

dependencies: Avalonia.Diagnostics.Common
It is a code analyzer that will generate DevToolsOptions.yaml as it persists in xml type configuration without using reflection('magic')

Avalonia.Diagnostics.Settings.Xml

dependencies: DevToolsOptions.yaml, Avalonia.Diagnostics.Common, Avalonia.Diagnostics.Settings.Generators.Xml (only in build).
contents:

  • DevToolsOptions.yaml (link)
  • XmlSettingStore (partial class)

Usage examples

In memory (Actual behavior)

public MainWindow()
{
   this.InitializeComponent();
   this.AttachDevTools();
}

With custom settings

public MainWindow()
{
   this.InitializeComponent();
   this.AttachDevTools()
       .With( new DevToolsOptions(){
                ShouldVisualizeDirtyRects = true,
                 Window = new WindowSettings(){
                    State = FullScreen,
                 },
              });
}

XML persistence

public MainWindow()
{
   this.InitializeComponent();
   this.AttachDevTools()
       .With( new DevToolsOptions(){
                ShouldVisualizeDirtyRects = true,
                 Window = new WindowSettings(){
                    State = FullScreen,
                 },
              })
       .With( new XmlSettingStore("Path"){
               Indent = true,
             });

}

Pros and cons

Pro:

  • Low impact on current operation
  • It does not use reflection at runtime
  • Customization of settings
  • Ability to store settings
  • ability to create custom providers for persistence of settings (REST,json,bson,yaml, ...)

Cons:

  • Requires Visual Studio 16.8 Preview 3 and .NET 5 Preview

Original message

In these PR #4731 #4762 I need to keep some settings (screenshot path, hot keys, favorite properties).

I would like to create a common way to save all present and future DevTools settings eg: windows location.

I think we could implement a system similar to the .net core or use that.

Do you have any suggestions?

Most helpful comment

Can we use Options pattern here?

this.AttachDevTools(new DevToolsOptions
{
    HotKeys = /* ... */,
    ScreenshotPath = "/screenshots",
    FavoriteProperties = new { /* ... */ } // doesn't overload default ones.
})

If developer want to use local file to store settings that should remember some dynamic props like FavoriteProperties, than we can have optional overload:

this.AttachDevTools(new DevToolsFileOptions(new FileInfo("/devtools-options.json")));

All 6 comments

Definitely somewhere in {SpecialFolder.LocalApplicationData}/AvaloniaUI/DevTools

Open questions:
1) Should we use versioning for those settings? How versioning would work? Would ti be Avalonia version or settings schema version?
2) Should we use JSON.NET for serialization? It's a heavy library and not every app will want to depend on that. It also might introduce nuget version conflicts.

Definitely somewhere in {SpecialFolder.LocalApplicationData}/AvaloniaUI/DevTools

Does {SpecialFolder.LocalApplicationData} exist on the mobile platform?

1. Should we use versioning for those settings? How versioning would work? Would ti be Avalonia version or settings schema version?

Before, we should understand if the settings we would like to memorize by machine or by application.

If for machine, we should store settings in {SpecialFolder.LocalApplicationData}/AvaloniaUI/DevTools/{AvaloniaVerison}/

if for app, i we should store settings in {SpecialFolder.LocalApplicationData}/AvaloniaUI/DevTools/{AvaloniaVerison}/{Company}/{App}/{AppVersion}/

if we decide that the config store like a dictionary, we could merge the versions based on the key.

  1. Should we use JSON.NET for serialization? It's a heavy library and not every app will want to depend on that. It also might introduce nuget version conflicts.

We could create providers for example: JsonConfingStore, YamlConfigStore, INIConfigStore, RestConfigStore, XMLConfigStore, etc. and deploy with separate nuget.

Does SpecialFolder.LocalApplicationData exist on the mobile platform?

Yes, special folders are mapped to relevant locations

Before, we should understand if the settings we would like to memorize by machine or by application.

It's counterproductive to force the user to reconfigure dev tools for each app

We could create providers for example: JsonConfingStore, YamlConfigStore, INIConfigStore, RestConfigStore, XMLConfigStore, etc. and deploy with separate nuget.

I'd rather not overcomplicate devtools that way. The built-in System.Xml should be enough for our needs.

Hi @kekekeks
What do you think of this method?

Can we use Options pattern here?

this.AttachDevTools(new DevToolsOptions
{
    HotKeys = /* ... */,
    ScreenshotPath = "/screenshots",
    FavoriteProperties = new { /* ... */ } // doesn't overload default ones.
})

If developer want to use local file to store settings that should remember some dynamic props like FavoriteProperties, than we can have optional overload:

this.AttachDevTools(new DevToolsFileOptions(new FileInfo("/devtools-options.json")));

Can we use Options pattern here?

I like this a lot!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Suriman picture Suriman  路  3Comments

kekekeks picture kekekeks  路  4Comments

ZZerker picture ZZerker  路  4Comments

GitHubington picture GitHubington  路  3Comments

x2bool picture x2bool  路  4Comments