Skip to content

Commit

Permalink
Make MarkupExtension.ProvideValue method inlinable for StaticResource…
Browse files Browse the repository at this point in the history
…Extension and ResolveByNameExtension (#17659)
  • Loading branch information
maxkatz6 authored Dec 3, 2024
1 parent 44a6f91 commit a530bbe
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Runtime.CompilerServices;
using Avalonia.Controls;
using Avalonia.Data.Core;

Expand All @@ -13,14 +14,17 @@ public ResolveByNameExtension(string name)

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<INameScope>();

if (nameScope is null)
return null;
var value = nameScope.FindAsync(Name);

var value = nameScope.FindAsync(name);

if(value.IsCompleted)
return value.GetResult();
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -22,9 +23,14 @@ public StaticResourceExtension(object resourceKey)

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.");
}
Expand Down Expand Up @@ -87,20 +93,16 @@ public StaticResourceExtension(object resourceKey)
{
// 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)
Expand Down

0 comments on commit a530bbe

Please sign in to comment.