diff --git a/README.md b/README.md
index 450544b2d2..1341b0694b 100644
--- a/README.md
+++ b/README.md
@@ -110,6 +110,11 @@ The `x:Name` generator can be configured via MsBuild properties that you can put
The generator will process only XAML files with base classes' namespaces matching the specified glob pattern(s).
Example: `MyApp.Presentation.*`, `MyApp.Presentation.Views;MyApp.Presentation.Controls`
+- `AvaloniaNameGeneratorViewFileNamingStrategy`
+ Possible values: `ClassName`, `NamespaceAndClassName`
+ Default value: `NamespaceAndClassName`
+ Determines how the automatically generated view files should be [named](https://github.com/AvaloniaUI/Avalonia.NameGenerator/issues/92).
+
The default values are given by:
```xml
@@ -119,6 +124,7 @@ The default values are given by:
internal
*
*
+ NamespaceAndClassName
diff --git a/src/Avalonia.NameGenerator.Sandbox/App.xaml.cs b/src/Avalonia.NameGenerator.Sandbox/App.xaml.cs
index 896de180ee..320d78bbd9 100644
--- a/src/Avalonia.NameGenerator.Sandbox/App.xaml.cs
+++ b/src/Avalonia.NameGenerator.Sandbox/App.xaml.cs
@@ -1,6 +1,5 @@
using Avalonia.Markup.Xaml;
using Avalonia.NameGenerator.Sandbox.ViewModels;
-using Avalonia.NameGenerator.Sandbox.Views;
namespace Avalonia.NameGenerator.Sandbox;
@@ -10,7 +9,7 @@ public class App : Application
public override void OnFrameworkInitializationCompleted()
{
- var view = new SignUpView
+ var view = new Views.SignUpView
{
ViewModel = new SignUpViewModel()
};
diff --git a/src/Avalonia.NameGenerator.Sandbox/Controls/SignUpView.xaml b/src/Avalonia.NameGenerator.Sandbox/Controls/SignUpView.xaml
new file mode 100644
index 0000000000..0f26a6fa71
--- /dev/null
+++ b/src/Avalonia.NameGenerator.Sandbox/Controls/SignUpView.xaml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.NameGenerator.Sandbox/Controls/SignUpView.xaml.cs b/src/Avalonia.NameGenerator.Sandbox/Controls/SignUpView.xaml.cs
new file mode 100644
index 0000000000..f9bff84f7a
--- /dev/null
+++ b/src/Avalonia.NameGenerator.Sandbox/Controls/SignUpView.xaml.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Reactive.Disposables;
+using Avalonia.NameGenerator.Sandbox.ViewModels;
+using Avalonia.ReactiveUI;
+using ReactiveUI;
+using ReactiveUI.Validation.Extensions;
+using ReactiveUI.Validation.Formatters;
+
+namespace Avalonia.NameGenerator.Sandbox.Controls;
+
+///
+/// This is a sample view class with typed x:Name references generated using
+/// .NET 5 source generators. The class has to be partial because x:Name
+/// references are living in a separate partial class file. See also:
+/// https://devblogs.microsoft.com/dotnet/new-c-source-generator-samples/
+///
+public partial class SignUpView : ReactiveUserControl
+{
+ public SignUpView()
+ {
+ // The InitializeComponent method is also generated automatically
+ // and lives in the autogenerated part of the partial class.
+ InitializeComponent();
+ this.WhenActivated(disposables =>
+ {
+ this.Bind(ViewModel, x => x.UserName, x => x.UserNameTextBox.Text)
+ .DisposeWith(disposables);
+ this.Bind(ViewModel, x => x.Password, x => x.PasswordTextBox.Text)
+ .DisposeWith(disposables);
+ this.Bind(ViewModel, x => x.ConfirmPassword, x => x.ConfirmPasswordTextBox.Text)
+ .DisposeWith(disposables);
+ this.BindCommand(ViewModel, x => x.SignUp, x => x.SignUpButton)
+ .DisposeWith(disposables);
+
+ this.BindValidation(ViewModel, x => x.UserName, x => x.UserNameValidation.Text)
+ .DisposeWith(disposables);
+ this.BindValidation(ViewModel, x => x.Password, x => x.PasswordValidation.Text)
+ .DisposeWith(disposables);
+ this.BindValidation(ViewModel, x => x.ConfirmPassword, x => x.ConfirmPasswordValidation.Text)
+ .DisposeWith(disposables);
+
+ var newLineFormatter = new SingleLineFormatter(Environment.NewLine);
+ this.BindValidation(ViewModel, x => x.CompoundValidation.Text, newLineFormatter)
+ .DisposeWith(disposables);
+
+ // The references to text boxes below are also auto generated.
+ // Use Ctrl+Click in order to view the generated sources.
+ UserNameTextBox.Text = "Joseph!";
+ PasswordTextBox.Text = "1234";
+ ConfirmPasswordTextBox.Text = "1234";
+ });
+ }
+}
\ No newline at end of file
diff --git a/src/Avalonia.NameGenerator.Sandbox/Views/SignUpView.xaml b/src/Avalonia.NameGenerator.Sandbox/Views/SignUpView.xaml
index a187d05da1..0a504b2cb4 100644
--- a/src/Avalonia.NameGenerator.Sandbox/Views/SignUpView.xaml
+++ b/src/Avalonia.NameGenerator.Sandbox/Views/SignUpView.xaml
@@ -4,36 +4,6 @@
x:Class="Avalonia.NameGenerator.Sandbox.Views.SignUpView">
-
-
-
-
-
-
-
-
+
diff --git a/src/Avalonia.NameGenerator.Sandbox/Views/SignUpView.xaml.cs b/src/Avalonia.NameGenerator.Sandbox/Views/SignUpView.xaml.cs
index 98224655d9..152b53c9ba 100644
--- a/src/Avalonia.NameGenerator.Sandbox/Views/SignUpView.xaml.cs
+++ b/src/Avalonia.NameGenerator.Sandbox/Views/SignUpView.xaml.cs
@@ -1,10 +1,7 @@
-using System;
-using System.Reactive.Disposables;
+using System.Reactive.Disposables;
using Avalonia.NameGenerator.Sandbox.ViewModels;
using Avalonia.ReactiveUI;
using ReactiveUI;
-using ReactiveUI.Validation.Extensions;
-using ReactiveUI.Validation.Formatters;
namespace Avalonia.NameGenerator.Sandbox.Views;
@@ -23,31 +20,9 @@ public partial class SignUpView : ReactiveWindow
InitializeComponent();
this.WhenActivated(disposables =>
{
- this.Bind(ViewModel, x => x.UserName, x => x.UserNameTextBox.Text)
+ this.WhenAnyValue(view => view.ViewModel)
+ .BindTo(this, view => view.SignUpControl.ViewModel)
.DisposeWith(disposables);
- this.Bind(ViewModel, x => x.Password, x => x.PasswordTextBox.Text)
- .DisposeWith(disposables);
- this.Bind(ViewModel, x => x.ConfirmPassword, x => x.ConfirmPasswordTextBox.Text)
- .DisposeWith(disposables);
- this.BindCommand(ViewModel, x => x.SignUp, x => x.SignUpButton)
- .DisposeWith(disposables);
-
- this.BindValidation(ViewModel, x => x.UserName, x => x.UserNameValidation.Text)
- .DisposeWith(disposables);
- this.BindValidation(ViewModel, x => x.Password, x => x.PasswordValidation.Text)
- .DisposeWith(disposables);
- this.BindValidation(ViewModel, x => x.ConfirmPassword, x => x.ConfirmPasswordValidation.Text)
- .DisposeWith(disposables);
-
- var newLineFormatter = new SingleLineFormatter(Environment.NewLine);
- this.BindValidation(ViewModel, x => x.CompoundValidation.Text, newLineFormatter)
- .DisposeWith(disposables);
-
- // The references to text boxes below are also auto generated.
- // Use Ctrl+Click in order to view the generated sources.
- UserNameTextBox.Text = "Joseph!";
- PasswordTextBox.Text = "1234";
- ConfirmPasswordTextBox.Text = "1234";
});
}
}
\ No newline at end of file
diff --git a/src/Avalonia.NameGenerator.Tests/Views/View.cs b/src/Avalonia.NameGenerator.Tests/Views/View.cs
index 37091e950b..837dc76024 100644
--- a/src/Avalonia.NameGenerator.Tests/Views/View.cs
+++ b/src/Avalonia.NameGenerator.Tests/Views/View.cs
@@ -3,9 +3,7 @@ using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
-
using Avalonia.Controls;
-
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
diff --git a/src/Avalonia.NameGenerator.Tests/XamlXNameResolverTests.cs b/src/Avalonia.NameGenerator.Tests/XamlXNameResolverTests.cs
index 90f0f64a50..9d54e183b7 100644
--- a/src/Avalonia.NameGenerator.Tests/XamlXNameResolverTests.cs
+++ b/src/Avalonia.NameGenerator.Tests/XamlXNameResolverTests.cs
@@ -24,7 +24,7 @@ public class XamlXNameResolverTests
Assert.NotEmpty(controls);
Assert.Equal(1, controls.Count);
Assert.Equal("UserNameTextBox", controls[0].Name);
- Assert.Equal(typeof(TextBox).FullName, controls[0].TypeName);
+ Assert.Contains(typeof(TextBox).FullName!, controls[0].TypeName);
}
[Theory]
@@ -40,9 +40,9 @@ public class XamlXNameResolverTests
Assert.Equal("UserNameTextBox", controls[0].Name);
Assert.Equal("PasswordTextBox", controls[1].Name);
Assert.Equal("SignUpButton", controls[2].Name);
- Assert.Equal(typeof(TextBox).FullName, controls[0].TypeName);
- Assert.Equal(typeof(TextBox).FullName, controls[1].TypeName);
- Assert.Equal(typeof(Button).FullName, controls[2].TypeName);
+ Assert.Contains(typeof(TextBox).FullName!, controls[0].TypeName);
+ Assert.Contains(typeof(TextBox).FullName!, controls[1].TypeName);
+ Assert.Contains(typeof(Button).FullName!, controls[2].TypeName);
}
[Fact]
@@ -56,9 +56,9 @@ public class XamlXNameResolverTests
Assert.Equal("ClrNamespaceRoutedViewHost", controls[0].Name);
Assert.Equal("UriRoutedViewHost", controls[1].Name);
Assert.Equal("UserNameTextBox", controls[2].Name);
- Assert.Equal(typeof(RoutedViewHost).FullName, controls[0].TypeName);
- Assert.Equal(typeof(RoutedViewHost).FullName, controls[1].TypeName);
- Assert.Equal("Controls.CustomTextBox", controls[2].TypeName);
+ Assert.Contains(typeof(RoutedViewHost).FullName!, controls[0].TypeName);
+ Assert.Contains(typeof(RoutedViewHost).FullName!, controls[1].TypeName);
+ Assert.Contains("Controls.CustomTextBox", controls[2].TypeName);
}
[Fact]
@@ -70,17 +70,12 @@ public class XamlXNameResolverTests
var currentControl = controls[0];
Assert.Equal("Root", currentControl.Name);
- Assert.Equal("Sample.App.BaseView", currentControl.TypeName);
- Assert.Equal(1, currentControl.GenericTypeArguments.Count);
- Assert.Equal(typeof(string).FullName, currentControl.GenericTypeArguments[0]);
- Assert.Equal("global::Sample.App.BaseView", currentControl.PrintableTypeName);
+ Assert.Equal("global::Sample.App.BaseView", currentControl.TypeName);
currentControl = controls[1];
Assert.Equal("NotAsRootNode", currentControl.Name);
- Assert.Equal("Sample.App.BaseView", currentControl.TypeName);
- Assert.Equal(1, currentControl.GenericTypeArguments.Count);
- Assert.Equal(typeof(int).FullName, currentControl.GenericTypeArguments[0]);
- Assert.Equal("global::Sample.App.BaseView", currentControl.PrintableTypeName);
+ Assert.Contains("Sample.App.BaseView", currentControl.TypeName);
+ Assert.Equal("global::Sample.App.BaseView", currentControl.TypeName);
}
[Fact]
@@ -102,8 +97,8 @@ public class XamlXNameResolverTests
Assert.Equal(2, controls.Count);
Assert.Equal("UserNameTextBox", controls[0].Name);
Assert.Equal("NamedListBox", controls[1].Name);
- Assert.Equal(typeof(TextBox).FullName, controls[0].TypeName);
- Assert.Equal(typeof(ListBox).FullName, controls[1].TypeName);
+ Assert.Contains(typeof(TextBox).FullName!, controls[0].TypeName);
+ Assert.Contains(typeof(ListBox).FullName!, controls[1].TypeName);
}
[Fact]
diff --git a/src/Avalonia.NameGenerator/Domain/ICodeGenerator.cs b/src/Avalonia.NameGenerator/Domain/ICodeGenerator.cs
index 077160e281..a422655ca1 100644
--- a/src/Avalonia.NameGenerator/Domain/ICodeGenerator.cs
+++ b/src/Avalonia.NameGenerator/Domain/ICodeGenerator.cs
@@ -5,5 +5,5 @@ namespace Avalonia.NameGenerator.Domain;
internal interface ICodeGenerator
{
- string GenerateCode(string className, string nameSpace, IXamlType XamlType, IEnumerable names);
+ string GenerateCode(string className, string nameSpace, IXamlType xamlType, IEnumerable names);
}
\ No newline at end of file
diff --git a/src/Avalonia.NameGenerator/Domain/INameResolver.cs b/src/Avalonia.NameGenerator/Domain/INameResolver.cs
index 1ba2bf36e4..2fdb1581f8 100644
--- a/src/Avalonia.NameGenerator/Domain/INameResolver.cs
+++ b/src/Avalonia.NameGenerator/Domain/INameResolver.cs
@@ -1,6 +1,4 @@
using System.Collections.Generic;
-using System.Linq;
-
using XamlX.Ast;
namespace Avalonia.NameGenerator.Domain;
@@ -10,48 +8,4 @@ internal interface INameResolver
IReadOnlyList ResolveNames(XamlDocument xaml);
}
-internal class ResolvedName
-{
- public ResolvedName(string typeName, string name, string fieldModifier, IReadOnlyList genericTypeArguments)
- {
- TypeName = typeName;
- Name = name;
- FieldModifier = fieldModifier;
- GenericTypeArguments = genericTypeArguments;
- }
-
- public string TypeName { get; }
- public string Name { get; }
- public string FieldModifier { get; }
- public IReadOnlyList GenericTypeArguments { get; }
-
- public string PrintableTypeName =>
- GenericTypeArguments.Count == 0
- ? $"global::{TypeName}"
- : $@"global::{TypeName}<{string.Join(", ", GenericTypeArguments.Select(arg => $"global::{arg}"))}>";
-
- public void Deconstruct(out string typeName, out string name, out string fieldModifier)
- {
- typeName = TypeName;
- name = Name;
- fieldModifier = FieldModifier;
- }
-
- public override bool Equals(object obj)
- {
- if (obj is not ResolvedName name)
- {
- return false;
- }
-
- return name.TypeName == TypeName
- && name.Name == Name
- && name.FieldModifier == FieldModifier
- && name.GenericTypeArguments.SequenceEqual(GenericTypeArguments);
- }
-
- public override int GetHashCode()
- {
- return (TypeName, Name, FieldModifier).GetHashCode();
- }
-}
\ No newline at end of file
+internal record ResolvedName(string TypeName, string Name, string FieldModifier);
\ No newline at end of file
diff --git a/src/Avalonia.NameGenerator/Generator.cs b/src/Avalonia.NameGenerator/Generator.cs
index 09fd02a51d..af94d7b016 100644
--- a/src/Avalonia.NameGenerator/Generator.cs
+++ b/src/Avalonia.NameGenerator/Generator.cs
@@ -21,7 +21,7 @@ public class AvaloniaNameSourceGenerator : ISourceGenerator
{
var generator = CreateNameGenerator(context);
var partials = generator.GenerateNameReferences(context.AdditionalFiles);
- foreach (var partial in partials) context.AddSource(partial.FileName, partial.Content);
+ foreach (var (fileName, content) in partials) context.AddSource(fileName, content);
}
catch (Exception exception)
{
@@ -33,7 +33,6 @@ public class AvaloniaNameSourceGenerator : ISourceGenerator
{
var options = new GeneratorOptions(context);
var types = new RoslynTypeSystem((CSharpCompilation)context.Compilation);
- var defaultFieldModifier = options.AvaloniaNameGeneratorDefaultFieldModifier.ToString().ToLowerInvariant();
ICodeGenerator generator = options.AvaloniaNameGeneratorBehavior switch {
Behavior.OnlyProperties => new OnlyPropertiesCodeGenerator(),
Behavior.InitializeComponent => new InitializeComponentCodeGenerator(types),
@@ -42,10 +41,11 @@ public class AvaloniaNameSourceGenerator : ISourceGenerator
var compiler = MiniCompiler.CreateDefault(types, MiniCompiler.AvaloniaXmlnsDefinitionAttribute);
return new AvaloniaNameGenerator(
+ options.AvaloniaNameGeneratorViewFileNamingStrategy,
new GlobPatternGroup(options.AvaloniaNameGeneratorFilterByPath),
new GlobPatternGroup(options.AvaloniaNameGeneratorFilterByNamespace),
new XamlXViewResolver(types, compiler, true, type => ReportInvalidType(context, type)),
- new XamlXNameResolver(defaultFieldModifier),
+ new XamlXNameResolver(options.AvaloniaNameGeneratorDefaultFieldModifier),
generator);
}
diff --git a/src/Avalonia.NameGenerator/Generator/AvaloniaNameGenerator.cs b/src/Avalonia.NameGenerator/Generator/AvaloniaNameGenerator.cs
index 6b8b410562..968f8876c2 100644
--- a/src/Avalonia.NameGenerator/Generator/AvaloniaNameGenerator.cs
+++ b/src/Avalonia.NameGenerator/Generator/AvaloniaNameGenerator.cs
@@ -1,3 +1,4 @@
+using System;
using System.Collections.Generic;
using System.Linq;
using Avalonia.NameGenerator.Domain;
@@ -7,6 +8,7 @@ namespace Avalonia.NameGenerator.Generator;
internal class AvaloniaNameGenerator : INameGenerator
{
+ private readonly ViewFileNamingStrategy _naming;
private readonly IGlobPattern _pathPattern;
private readonly IGlobPattern _namespacePattern;
private readonly IViewResolver _classes;
@@ -14,12 +16,14 @@ internal class AvaloniaNameGenerator : INameGenerator
private readonly ICodeGenerator _code;
public AvaloniaNameGenerator(
+ ViewFileNamingStrategy naming,
IGlobPattern pathPattern,
IGlobPattern namespacePattern,
IViewResolver classes,
INameResolver names,
ICodeGenerator code)
{
+ _naming = naming;
_pathPattern = pathPattern;
_namespacePattern = namespacePattern;
_classes = classes;
@@ -44,9 +48,16 @@ internal class AvaloniaNameGenerator : INameGenerator
from view in resolveViews
let names = _names.ResolveNames(view.Xaml)
let code = _code.GenerateCode(view.ClassName, view.Namespace, view.XamlType, names)
- let fileName = $"{view.ClassName}.g.cs"
+ let fileName = ResolveViewFileName(view, _naming)
select new GeneratedPartialClass(fileName, code);
return query.ToList();
}
+
+ private static string ResolveViewFileName(ResolvedView view, ViewFileNamingStrategy strategy) => strategy switch
+ {
+ ViewFileNamingStrategy.ClassName => $"{view.ClassName}.g.cs",
+ ViewFileNamingStrategy.NamespaceAndClassName => $"{view.Namespace}.{view.ClassName}.g.cs",
+ _ => throw new ArgumentOutOfRangeException(nameof(strategy), strategy, "Unknown naming strategy!")
+ };
}
\ No newline at end of file
diff --git a/src/Avalonia.NameGenerator/Generator/InitializeComponentCodeGenerator.cs b/src/Avalonia.NameGenerator/Generator/InitializeComponentCodeGenerator.cs
index e4ab64e36f..66daea8bcb 100644
--- a/src/Avalonia.NameGenerator/Generator/InitializeComponentCodeGenerator.cs
+++ b/src/Avalonia.NameGenerator/Generator/InitializeComponentCodeGenerator.cs
@@ -32,8 +32,7 @@ internal class InitializeComponentCodeGenerator: ICodeGenerator
var initializations = new List();
foreach (var resolvedName in names)
{
- var (_, name, fieldModifier) = resolvedName;
- string typeName = resolvedName.PrintableTypeName;
+ var (typeName, name, fieldModifier) = resolvedName;
properties.Add($" {fieldModifier} {typeName} {name};");
initializations.Add($" {name} = this.FindControl<{typeName}>(\"{name}\");");
}
diff --git a/src/Avalonia.NameGenerator/Generator/OnlyPropertiesCodeGenerator.cs b/src/Avalonia.NameGenerator/Generator/OnlyPropertiesCodeGenerator.cs
index 2aa5dcf2c5..ba8b1b59a5 100644
--- a/src/Avalonia.NameGenerator/Generator/OnlyPropertiesCodeGenerator.cs
+++ b/src/Avalonia.NameGenerator/Generator/OnlyPropertiesCodeGenerator.cs
@@ -11,8 +11,8 @@ internal class OnlyPropertiesCodeGenerator : ICodeGenerator
{
var namedControls = names
.Select(info => " " +
- $"{info.FieldModifier} {info.PrintableTypeName} {info.Name} => " +
- $"this.FindControl<{info.PrintableTypeName}>(\"{info.Name}\");")
+ $"{info.FieldModifier} {info.TypeName} {info.Name} => " +
+ $"this.FindControl<{info.TypeName}>(\"{info.Name}\");")
.ToList();
var lines = string.Join("\n", namedControls);
return $@"//
diff --git a/src/Avalonia.NameGenerator/Generator/XamlXNameResolver.cs b/src/Avalonia.NameGenerator/Generator/XamlXNameResolver.cs
index af0bc75403..746a81f0fc 100644
--- a/src/Avalonia.NameGenerator/Generator/XamlXNameResolver.cs
+++ b/src/Avalonia.NameGenerator/Generator/XamlXNameResolver.cs
@@ -1,9 +1,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
-
using Avalonia.NameGenerator.Domain;
-
using XamlX;
using XamlX.Ast;
@@ -14,9 +12,9 @@ internal class XamlXNameResolver : INameResolver, IXamlAstVisitor
private readonly List _items = new();
private readonly string _defaultFieldModifier;
- public XamlXNameResolver(string defaultFieldModifier = "internal")
+ public XamlXNameResolver(DefaultFieldModifier defaultFieldModifier = DefaultFieldModifier.Internal)
{
- _defaultFieldModifier = defaultFieldModifier;
+ _defaultFieldModifier = defaultFieldModifier.ToString().ToLowerInvariant();
}
public IReadOnlyList ResolveNames(XamlDocument xaml)
@@ -50,10 +48,13 @@ internal class XamlXNameResolver : INameResolver, IXamlAstVisitor
propertyValueNode.Values[0] is XamlAstTextNode text)
{
var fieldModifier = TryGetFieldModifier(objectNode);
- string typeName = $@"{clrType.Namespace}.{clrType.Name}";
- IReadOnlyList typeAgs = clrType.GenericArguments.Select(arg => arg.FullName).ToImmutableList();
+ var typeName = $@"{clrType.Namespace}.{clrType.Name}";
+ var typeAgs = clrType.GenericArguments.Select(arg => arg.FullName).ToImmutableList();
+ var genericTypeName = typeAgs.Count == 0
+ ? $"global::{typeName}"
+ : $@"global::{typeName}<{string.Join(", ", typeAgs.Select(arg => $"global::{arg}"))}>";
- var resolvedName = new ResolvedName(typeName, text.Text, fieldModifier, typeAgs);
+ var resolvedName = new ResolvedName(genericTypeName, text.Text, fieldModifier);
if (_items.Contains(resolvedName))
continue;
_items.Add(resolvedName);
diff --git a/src/Avalonia.NameGenerator/GeneratorOptions.cs b/src/Avalonia.NameGenerator/GeneratorOptions.cs
index 716926e326..f0b930a76d 100644
--- a/src/Avalonia.NameGenerator/GeneratorOptions.cs
+++ b/src/Avalonia.NameGenerator/GeneratorOptions.cs
@@ -9,6 +9,7 @@ public enum BuildProperties
AvaloniaNameGeneratorDefaultFieldModifier = 1,
AvaloniaNameGeneratorFilterByPath = 2,
AvaloniaNameGeneratorFilterByNamespace = 3,
+ AvaloniaNameGeneratorViewFileNamingStrategy = 4,
}
public enum DefaultFieldModifier
@@ -25,69 +26,49 @@ public enum Behavior
InitializeComponent = 1,
}
+public enum ViewFileNamingStrategy
+{
+ ClassName = 0,
+ NamespaceAndClassName = 1,
+}
+
public class GeneratorOptions
{
private readonly GeneratorExecutionContext _context;
public GeneratorOptions(GeneratorExecutionContext context) => _context = context;
- public Behavior AvaloniaNameGeneratorBehavior
- {
- get
- {
- const Behavior defaultBehavior = Behavior.InitializeComponent;
- var propertyValue = _context
- .GetMsBuildProperty(
- nameof(BuildProperties.AvaloniaNameGeneratorBehavior),
- defaultBehavior.ToString());
+ public Behavior AvaloniaNameGeneratorBehavior => GetEnumProperty(
+ BuildProperties.AvaloniaNameGeneratorBehavior,
+ Behavior.InitializeComponent);
- if (!Enum.TryParse(propertyValue, true, out Behavior behavior))
- return defaultBehavior;
- return behavior;
- }
- }
+ public DefaultFieldModifier AvaloniaNameGeneratorDefaultFieldModifier => GetEnumProperty(
+ BuildProperties.AvaloniaNameGeneratorDefaultFieldModifier,
+ DefaultFieldModifier.Internal);
- public DefaultFieldModifier AvaloniaNameGeneratorDefaultFieldModifier
- {
- get
- {
- const DefaultFieldModifier defaultFieldModifier = DefaultFieldModifier.Internal;
- var propertyValue = _context
- .GetMsBuildProperty(
- nameof(BuildProperties.AvaloniaNameGeneratorDefaultFieldModifier),
- defaultFieldModifier.ToString());
+ public ViewFileNamingStrategy AvaloniaNameGeneratorViewFileNamingStrategy => GetEnumProperty(
+ BuildProperties.AvaloniaNameGeneratorViewFileNamingStrategy,
+ ViewFileNamingStrategy.NamespaceAndClassName);
- if (!Enum.TryParse(propertyValue, true, out DefaultFieldModifier modifier))
- return defaultFieldModifier;
- return modifier;
- }
- }
+ public string[] AvaloniaNameGeneratorFilterByPath => GetStringArrayProperty(
+ BuildProperties.AvaloniaNameGeneratorFilterByPath,
+ "*");
- public string[] AvaloniaNameGeneratorFilterByPath
- {
- get
- {
- var propertyValue = _context.GetMsBuildProperty(
- nameof(BuildProperties.AvaloniaNameGeneratorFilterByPath),
- "*");
+ public string[] AvaloniaNameGeneratorFilterByNamespace => GetStringArrayProperty(
+ BuildProperties.AvaloniaNameGeneratorFilterByNamespace,
+ "*");
- if (propertyValue.Contains(";"))
- return propertyValue.Split(';');
- return new[] {propertyValue};
- }
+ private string[] GetStringArrayProperty(BuildProperties name, string defaultValue)
+ {
+ var key = name.ToString();
+ var value = _context.GetMsBuildProperty(key, defaultValue);
+ return value.Contains(";") ? value.Split(';') : new[] {value};
}
- public string[] AvaloniaNameGeneratorFilterByNamespace
+ private TEnum GetEnumProperty(BuildProperties name, TEnum defaultValue) where TEnum : struct
{
- get
- {
- var propertyValue = _context.GetMsBuildProperty(
- nameof(BuildProperties.AvaloniaNameGeneratorFilterByNamespace),
- "*");
-
- if (propertyValue.Contains(";"))
- return propertyValue.Split(';');
- return new[] {propertyValue};
- }
+ var key = name.ToString();
+ var value = _context.GetMsBuildProperty(key, defaultValue.ToString());
+ return Enum.TryParse(value, true, out TEnum behavior) ? behavior : defaultValue;
}
}
\ No newline at end of file