diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/ResolveByNameExtension.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/ResolveByNameExtension.cs index db6e69f00f..aaf0cb66f5 100644 --- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/ResolveByNameExtension.cs +++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/ResolveByNameExtension.cs @@ -1,4 +1,5 @@ using System; +using System.Runtime.CompilerServices; using Avalonia.Controls; using Avalonia.Data.Core; @@ -13,14 +14,17 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions public string Name { get; } - public object? ProvideValue(IServiceProvider serviceProvider) + public object? ProvideValue(IServiceProvider serviceProvider) => ProvideValue(serviceProvider, Name); + + [MethodImpl(MethodImplOptions.NoInlining)] + private static object? ProvideValue(IServiceProvider serviceProvider, string name) { var nameScope = serviceProvider.GetService(); if (nameScope is null) return null; - - var value = nameScope.FindAsync(Name); + + var value = nameScope.FindAsync(name); if(value.IsCompleted) return value.GetResult(); diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/StaticResourceExtension.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/StaticResourceExtension.cs index 6b048ef0d6..adc8ff7e58 100644 --- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/StaticResourceExtension.cs +++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/StaticResourceExtension.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Reflection; +using System.Runtime.CompilerServices; using Avalonia.Controls; using Avalonia.Markup.Data; using Avalonia.Markup.Xaml.Converters; @@ -22,9 +23,14 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions public object? ResourceKey { get; set; } - public object? ProvideValue(IServiceProvider serviceProvider) + // Keep instance method ProvideValue as simple as possible, increasing chance to inline it. + // With modern runtimes, inlining this method also helps to eliminate extension allocation completely. + public object? ProvideValue(IServiceProvider serviceProvider) => ProvideValue(serviceProvider, ResourceKey); + + [MethodImpl(MethodImplOptions.NoInlining)] + private static object? ProvideValue(IServiceProvider serviceProvider, object? resourceKey) { - if (ResourceKey is not { } resourceKey) + if (resourceKey is null) { throw new ArgumentException("StaticResourceExtension.ResourceKey must be set."); } @@ -87,20 +93,16 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions { // This is stored locally to avoid allocating closure in the outer scope. var localTargetType = targetType; - var localInstance = this; + var localKeyInstance = resourceKey; - DelayedBinding.Add(target, property, x => localInstance.GetValue(x, localTargetType)); + DelayedBinding.Add(target, property, x => + ColorToBrushConverter.Convert(x.FindResource(localKeyInstance), localTargetType)); return AvaloniaProperty.UnsetValue; } throw new KeyNotFoundException($"Static resource '{resourceKey}' not found."); } - private object? GetValue(StyledElement control, Type? targetType) - { - return ColorToBrushConverter.Convert(control.FindResource(ResourceKey!), targetType); - } - internal static ThemeVariant? GetDictionaryVariant(IAvaloniaXamlIlParentStackProvider? stack) { switch (stack)