Browse Source

feat: StringBuilderCache

pull/8460/head
Giuseppe Lippolis 4 years ago
parent
commit
ba2747b897
  1. 1
      src/Avalonia.Base/Avalonia.Base.csproj
  2. 4
      src/Avalonia.Base/Input/KeyGesture.cs
  3. 6
      src/Avalonia.Base/Logging/TraceLogSink.cs
  4. 4
      src/Avalonia.Base/Media/BoxShadow.cs
  5. 4
      src/Avalonia.Base/Media/BoxShadows.cs
  6. 4
      src/Avalonia.Base/Media/Fonts/FamilyNameCollection.cs
  7. 4
      src/Avalonia.Base/Media/HslColor.cs
  8. 4
      src/Avalonia.Base/Media/HsvColor.cs
  9. 68
      src/Avalonia.Base/StringBuilderCache.cs
  10. 5
      src/Avalonia.Base/Styling/NthChildSelector.cs
  11. 4
      src/Avalonia.Base/Styling/PropertyEqualsSelector.cs
  12. 4
      src/Avalonia.Base/Styling/TypeNameAndClassSelector.cs
  13. 1
      src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj
  14. 4
      src/Avalonia.Controls.ColorPicker/Helpers/ColorHelper.cs
  15. 8
      src/Avalonia.Controls.DataGrid/DataGrid.cs
  16. 8
      src/Avalonia.Controls/Converters/PlatformKeyGestureConverter.cs
  17. 4
      src/Avalonia.Controls/Documents/InlineCollection.cs
  18. 2
      src/Avalonia.Diagnostics/Diagnostics/VisualTreeDebug.cs
  19. 3
      src/Markup/Avalonia.Markup.Xaml.Loader/Avalonia.Markup.Xaml.Loader.csproj
  20. 4
      src/Windows/Avalonia.Win32/ClipboardFormats.cs
  21. 4
      src/Windows/Avalonia.Win32/Input/WindowsKeyboardDevice.cs
  22. 4
      src/Windows/Avalonia.Win32/OleDataObject.cs
  23. 1
      src/tools/Avalonia.Designer.HostApp/Avalonia.Designer.HostApp.csproj

1
src/Avalonia.Base/Avalonia.Base.csproj

@ -31,6 +31,7 @@
<InternalsVisibleTo Include="Avalonia.Skia.RenderTests, PublicKey=$(AvaloniaPublicKey)" /> <InternalsVisibleTo Include="Avalonia.Skia.RenderTests, PublicKey=$(AvaloniaPublicKey)" />
<InternalsVisibleTo Include="Avalonia.Skia.UnitTests, PublicKey=$(AvaloniaPublicKey)" /> <InternalsVisibleTo Include="Avalonia.Skia.UnitTests, PublicKey=$(AvaloniaPublicKey)" />
<InternalsVisibleTo Include="Avalonia.UnitTests, PublicKey=$(AvaloniaPublicKey)" /> <InternalsVisibleTo Include="Avalonia.UnitTests, PublicKey=$(AvaloniaPublicKey)" />
<InternalsVisibleTo Include="Avalonia.Win32, PublicKey=$(AvaloniaPublicKey)" />
<InternalsVisibleTo Include="Avalonia.Web.Blazor, PublicKey=$(AvaloniaPublicKey)" /> <InternalsVisibleTo Include="Avalonia.Web.Blazor, PublicKey=$(AvaloniaPublicKey)" />
<InternalsVisibleTo Include="DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7"/> <InternalsVisibleTo Include="DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7"/>
</ItemGroup> </ItemGroup>

4
src/Avalonia.Base/Input/KeyGesture.cs

@ -106,7 +106,7 @@ namespace Avalonia.Input
public override string ToString() public override string ToString()
{ {
var s = new StringBuilder(); var s = StringBuilderCache.Acquire();
static void Plus(StringBuilder s) static void Plus(StringBuilder s)
{ {
@ -142,7 +142,7 @@ namespace Avalonia.Input
Plus(s); Plus(s);
s.Append(Key); s.Append(Key);
return s.ToString(); return StringBuilderCache.GetStringAndRelease(s);
} }
public bool Matches(KeyEventArgs keyEvent) => public bool Matches(KeyEventArgs keyEvent) =>

6
src/Avalonia.Base/Logging/TraceLogSink.cs

@ -46,7 +46,7 @@ namespace Avalonia.Logging
object? source, object? source,
object?[]? values) object?[]? values)
{ {
var result = new StringBuilder(template.Length); var result = StringBuilderCache.Acquire(template.Length);
var r = new CharacterReader(template.AsSpan()); var r = new CharacterReader(template.AsSpan());
var i = 0; var i = 0;
@ -89,7 +89,7 @@ namespace Avalonia.Logging
result.Append(')'); result.Append(')');
} }
return result.ToString(); return StringBuilderCache.GetStringAndRelease(result);
} }
private static string Format( private static string Format(
@ -98,7 +98,7 @@ namespace Avalonia.Logging
object? source, object? source,
object?[] v) object?[] v)
{ {
var result = new StringBuilder(template.Length); var result = StringBuilderCache.Acquire(template.Length);
var r = new CharacterReader(template.AsSpan()); var r = new CharacterReader(template.AsSpan());
var i = 0; var i = 0;

4
src/Avalonia.Base/Media/BoxShadow.cs

@ -80,7 +80,7 @@ namespace Avalonia.Media
public override string ToString() public override string ToString()
{ {
var sb = new StringBuilder(); var sb = StringBuilderCache.Acquire();
if (IsEmpty) if (IsEmpty)
{ {
@ -114,7 +114,7 @@ namespace Avalonia.Media
sb.AppendFormat(" {0}", Color.ToString()); sb.AppendFormat(" {0}", Color.ToString());
return sb.ToString(); return StringBuilderCache.GetStringAndRelease(sb);
} }
public static unsafe BoxShadow Parse(string s) public static unsafe BoxShadow Parse(string s)

4
src/Avalonia.Base/Media/BoxShadows.cs

@ -45,7 +45,7 @@ namespace Avalonia.Media
public override string ToString() public override string ToString()
{ {
var sb = new StringBuilder(); var sb = StringBuilderCache.Acquire();
if (Count == 0) if (Count == 0)
{ {
@ -57,7 +57,7 @@ namespace Avalonia.Media
sb.AppendFormat("{0} ", boxShadow.ToString()); sb.AppendFormat("{0} ", boxShadow.ToString());
} }
return sb.ToString(); return StringBuilderCache.GetStringAndRelease(sb);
} }

4
src/Avalonia.Base/Media/Fonts/FamilyNameCollection.cs

@ -77,7 +77,7 @@ namespace Avalonia.Media.Fonts
/// </returns> /// </returns>
public override string ToString() public override string ToString()
{ {
var builder = new StringBuilder(); var builder = StringBuilderCache.Acquire();
for (var index = 0; index < Names.Count; index++) for (var index = 0; index < Names.Count; index++)
{ {
@ -91,7 +91,7 @@ namespace Avalonia.Media.Fonts
builder.Append(", "); builder.Append(", ");
} }
return builder.ToString(); return StringBuilderCache.GetStringAndRelease(builder);
} }
/// <summary> /// <summary>

4
src/Avalonia.Base/Media/HslColor.cs

@ -202,7 +202,7 @@ namespace Avalonia.Media
/// <inheritdoc/> /// <inheritdoc/>
public override string ToString() public override string ToString()
{ {
var sb = new StringBuilder(); var sb = StringBuilderCache.Acquire();
// Use a format similar to CSS. However: // Use a format similar to CSS. However:
// - To ensure precision is never lost, allow decimal places. // - To ensure precision is never lost, allow decimal places.
@ -225,7 +225,7 @@ namespace Avalonia.Media
sb.Append(A.ToString(CultureInfo.InvariantCulture)); sb.Append(A.ToString(CultureInfo.InvariantCulture));
sb.Append(')'); sb.Append(')');
return sb.ToString(); return StringBuilderCache.GetStringAndRelease(sb);
} }
/// <summary> /// <summary>

4
src/Avalonia.Base/Media/HsvColor.cs

@ -202,7 +202,7 @@ namespace Avalonia.Media
/// <inheritdoc/> /// <inheritdoc/>
public override string ToString() public override string ToString()
{ {
var sb = new StringBuilder(); var sb = StringBuilderCache.Acquire();
// Use a format similar to CSS. However: // Use a format similar to CSS. However:
// - To ensure precision is never lost, allow decimal places. // - To ensure precision is never lost, allow decimal places.
@ -225,7 +225,7 @@ namespace Avalonia.Media
sb.Append(A.ToString(CultureInfo.InvariantCulture)); sb.Append(A.ToString(CultureInfo.InvariantCulture));
sb.Append(')'); sb.Append(')');
return sb.ToString(); return StringBuilderCache.GetStringAndRelease(sb);
} }
/// <summary> /// <summary>

68
src/Avalonia.Base/StringBuilderCache.cs

@ -0,0 +1,68 @@
// This file is imported from dotnet/runtime
// Source Link: https://github.com/dotnet/runtime/blob/e63d21947e734db2da5093510a6636b5b7fb45b5/src/libraries/Common/src/System/Text/StringBuilderCache.cs
// Commit: a9c5ead on Feb 10, 2021, https://github.com/dotnet/runtime/commit/a9c5eadd951dcba73167f72cc624eb790573663a
//
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Text;
namespace Avalonia;
// <summary>Provide a cached reusable instance of stringbuilder per thread.</summary>
internal static class StringBuilderCache
{
// The value 360 was chosen in discussion with performance experts as a compromise between using
// as little memory per thread as possible and still covering a large part of short-lived
// StringBuilder creations on the startup path of VS designers.
internal const int MaxBuilderSize = 360;
private const int DefaultCapacity = 16; // == StringBuilder.DefaultCapacity
// WARNING: We allow diagnostic tools to directly inspect this member (t_cachedInstance).
// See https://github.com/dotnet/corert/blob/master/Documentation/design-docs/diagnostics/diagnostics-tools-contract.md for more details.
// Please do not change the type, the name, or the semantic usage of this member without understanding the implication for tools.
// Get in touch with the diagnostics team if you have questions.
[ThreadStatic]
private static StringBuilder? t_cachedInstance;
/// <summary>Get a StringBuilder for the specified capacity.</summary>
/// <remarks>If a StringBuilder of an appropriate size is cached, it will be returned and the cache emptied.</remarks>
public static StringBuilder Acquire(int capacity = DefaultCapacity)
{
if (capacity <= MaxBuilderSize)
{
StringBuilder? sb = t_cachedInstance;
if (sb != null)
{
// Avoid stringbuilder block fragmentation by getting a new StringBuilder
// when the requested size is larger than the current capacity
if (capacity <= sb.Capacity)
{
t_cachedInstance = null;
sb.Clear();
return sb;
}
}
}
return new StringBuilder(capacity);
}
/// <summary>Place the specified builder in the cache if it is not too big.</summary>
public static void Release(StringBuilder sb)
{
if (sb.Capacity <= MaxBuilderSize)
{
t_cachedInstance = sb;
}
}
/// <summary>ToString() the stringbuilder, Release it to the cache, and return the resulting string.</summary>
public static string GetStringAndRelease(StringBuilder sb)
{
string result = sb.ToString();
Release(sb);
return result;
}
}

5
src/Avalonia.Base/Styling/NthChildSelector.cs

@ -110,7 +110,8 @@ namespace Avalonia.Styling
public override string ToString() public override string ToString()
{ {
var expectedCapacity = NthLastChildSelectorName.Length + 8; var expectedCapacity = NthLastChildSelectorName.Length + 8;
var stringBuilder = new StringBuilder(_previous?.ToString(), expectedCapacity); var stringBuilder = StringBuilderCache.Acquire(expectedCapacity);
stringBuilder.Append(_previous?.ToString());
stringBuilder.Append(':'); stringBuilder.Append(':');
stringBuilder.Append(_reversed ? NthLastChildSelectorName : NthChildSelectorName); stringBuilder.Append(_reversed ? NthLastChildSelectorName : NthChildSelectorName);
@ -140,7 +141,7 @@ namespace Avalonia.Styling
stringBuilder.Append(')'); stringBuilder.Append(')');
return stringBuilder.ToString(); return StringBuilderCache.GetStringAndRelease(stringBuilder);
} }
} }
} }

4
src/Avalonia.Base/Styling/PropertyEqualsSelector.cs

@ -42,7 +42,7 @@ namespace Avalonia.Styling
{ {
if (_selectorString == null) if (_selectorString == null)
{ {
var builder = new StringBuilder(); var builder = StringBuilderCache.Acquire();
if (_previous != null) if (_previous != null)
{ {
@ -67,7 +67,7 @@ namespace Avalonia.Styling
builder.Append(_value ?? string.Empty); builder.Append(_value ?? string.Empty);
builder.Append(']'); builder.Append(']');
_selectorString = builder.ToString(); _selectorString = StringBuilderCache.GetStringAndRelease(builder);
} }
return _selectorString; return _selectorString;

4
src/Avalonia.Base/Styling/TypeNameAndClassSelector.cs

@ -144,7 +144,7 @@ namespace Avalonia.Styling
private string BuildSelectorString() private string BuildSelectorString()
{ {
var builder = new StringBuilder(); var builder = StringBuilderCache.Acquire();
if (_previous != null) if (_previous != null)
{ {
@ -184,7 +184,7 @@ namespace Avalonia.Styling
} }
} }
return builder.ToString(); return StringBuilderCache.GetStringAndRelease(builder);
} }
} }
} }

1
src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj

@ -50,6 +50,7 @@
<Compile Include="../Avalonia.Base/Utilities/MathUtilities.cs"> <Compile Include="../Avalonia.Base/Utilities/MathUtilities.cs">
<Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link> <Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
</Compile> </Compile>
<Compile Include="..\Avalonia.Base\StringBuilderCache.cs" Link="StringBuilderCache.cs" />
<Compile Include="..\Markup\Avalonia.Markup\Markup\Parsers\ArgumentListParser.cs"> <Compile Include="..\Markup\Avalonia.Markup\Markup\Parsers\ArgumentListParser.cs">
<Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link> <Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
</Compile> </Compile>

4
src/Avalonia.Controls.ColorPicker/Helpers/ColorHelper.cs

@ -109,7 +109,7 @@ namespace Avalonia.Controls.Primitives
// Cache results for next time as well // Cache results for next time as well
if (closestKnownColor != KnownColor.None) if (closestKnownColor != KnownColor.None)
{ {
StringBuilder sb = new StringBuilder(); var sb = StringBuilderCache.Acquire();
string name = closestKnownColor.ToString(); string name = closestKnownColor.ToString();
// Add spaces converting PascalCase to human-readable names // Add spaces converting PascalCase to human-readable names
@ -124,7 +124,7 @@ namespace Avalonia.Controls.Primitives
sb.Append(name[i]); sb.Append(name[i]);
} }
string displayName = sb.ToString(); string displayName = StringBuilderCache.GetStringAndRelease(sb);
lock (cacheMutex) lock (cacheMutex)
{ {

8
src/Avalonia.Controls.DataGrid/DataGrid.cs

@ -5990,7 +5990,7 @@ namespace Avalonia.Controls
/// <returns>The formatted string.</returns> /// <returns>The formatted string.</returns>
private string FormatClipboardContent(DataGridRowClipboardEventArgs e) private string FormatClipboardContent(DataGridRowClipboardEventArgs e)
{ {
var text = new StringBuilder(); var text = StringBuilderCache.Acquire();
var clipboardRowContent = e.ClipboardRowContent; var clipboardRowContent = e.ClipboardRowContent;
var numberOfItem = clipboardRowContent.Count; var numberOfItem = clipboardRowContent.Count;
for (int cellIndex = 0; cellIndex < numberOfItem; cellIndex++) for (int cellIndex = 0; cellIndex < numberOfItem; cellIndex++)
@ -6007,7 +6007,7 @@ namespace Avalonia.Controls
text.Append('\n'); text.Append('\n');
} }
} }
return text.ToString(); return StringBuilderCache.GetStringAndRelease(text);
} }
/// <summary> /// <summary>
@ -6022,7 +6022,7 @@ namespace Avalonia.Controls
if (ctrl && !shift && !alt && ClipboardCopyMode != DataGridClipboardCopyMode.None && SelectedItems.Count > 0) if (ctrl && !shift && !alt && ClipboardCopyMode != DataGridClipboardCopyMode.None && SelectedItems.Count > 0)
{ {
StringBuilder textBuilder = new StringBuilder(); var textBuilder = StringBuilderCache.Acquire();
if (ClipboardCopyMode == DataGridClipboardCopyMode.IncludeHeader) if (ClipboardCopyMode == DataGridClipboardCopyMode.IncludeHeader)
{ {
@ -6048,7 +6048,7 @@ namespace Avalonia.Controls
textBuilder.Append(FormatClipboardContent(itemArgs)); textBuilder.Append(FormatClipboardContent(itemArgs));
} }
string text = textBuilder.ToString(); string text = StringBuilderCache.GetStringAndRelease(textBuilder);
if (!string.IsNullOrEmpty(text)) if (!string.IsNullOrEmpty(text))
{ {

8
src/Avalonia.Controls/Converters/PlatformKeyGestureConverter.cs

@ -62,7 +62,7 @@ namespace Avalonia.Controls.Converters
private static string ToString(KeyGesture gesture, string meta) private static string ToString(KeyGesture gesture, string meta)
{ {
var s = new StringBuilder(); var s = StringBuilderCache.Acquire();
static void Plus(StringBuilder s) static void Plus(StringBuilder s)
{ {
@ -98,12 +98,12 @@ namespace Avalonia.Controls.Converters
Plus(s); Plus(s);
s.Append(ToString(gesture.Key)); s.Append(ToString(gesture.Key));
return s.ToString(); return StringBuilderCache.GetStringAndRelease(s);
} }
private static string ToOSXString(KeyGesture gesture) private static string ToOSXString(KeyGesture gesture)
{ {
var s = new StringBuilder(); var s = StringBuilderCache.Acquire();
if (gesture.KeyModifiers.HasAllFlags(KeyModifiers.Control)) if (gesture.KeyModifiers.HasAllFlags(KeyModifiers.Control))
{ {
@ -127,7 +127,7 @@ namespace Avalonia.Controls.Converters
s.Append(ToOSXString(gesture.Key)); s.Append(ToOSXString(gesture.Key));
return s.ToString(); return StringBuilderCache.GetStringAndRelease(s);
} }
private static string ToString(Key key) private static string ToString(Key key)

4
src/Avalonia.Controls/Documents/InlineCollection.cs

@ -78,14 +78,14 @@ namespace Avalonia.Controls.Documents
return _text; return _text;
} }
var builder = new StringBuilder(); var builder = StringBuilderCache.Acquire();
foreach (var inline in this) foreach (var inline in this)
{ {
inline.AppendText(builder); inline.AppendText(builder);
} }
return builder.ToString(); return StringBuilderCache.GetStringAndRelease(builder);
} }
set set
{ {

2
src/Avalonia.Diagnostics/Diagnostics/VisualTreeDebug.cs

@ -10,7 +10,7 @@ namespace Avalonia.Diagnostics
{ {
public static string PrintVisualTree(IVisual visual) public static string PrintVisualTree(IVisual visual)
{ {
StringBuilder result = new StringBuilder(); var result = new StringBuilder();
PrintVisualTree(visual, result, 0); PrintVisualTree(visual, result, 0);
return result.ToString(); return result.ToString();
} }

3
src/Markup/Avalonia.Markup.Xaml.Loader/Avalonia.Markup.Xaml.Loader.csproj

@ -7,6 +7,9 @@
<DefineConstants>$(DefineConstants);XAMLX_INTERNAL</DefineConstants> <DefineConstants>$(DefineConstants);XAMLX_INTERNAL</DefineConstants>
</PropertyGroup> </PropertyGroup>
<Import Project="IncludeXamlIlSre.props" /> <Import Project="IncludeXamlIlSre.props" />
<ItemGroup>
<Compile Include="..\..\Avalonia.Base\StringBuilderCache.cs" Link="StringBuilderCache.cs" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="System.Reflection.Emit" Version="4.3.0" /> <PackageReference Include="System.Reflection.Emit" Version="4.3.0" />
</ItemGroup> </ItemGroup>

4
src/Windows/Avalonia.Win32/ClipboardFormats.cs

@ -35,9 +35,9 @@ namespace Avalonia.Win32
private static string QueryFormatName(ushort format) private static string QueryFormatName(ushort format)
{ {
StringBuilder sb = new StringBuilder(MAX_FORMAT_NAME_LENGTH); var sb = StringBuilderCache.Acquire(MAX_FORMAT_NAME_LENGTH);
if (UnmanagedMethods.GetClipboardFormatName(format, sb, sb.Capacity) > 0) if (UnmanagedMethods.GetClipboardFormatName(format, sb, sb.Capacity) > 0)
return sb.ToString(); return StringBuilderCache.GetStringAndRelease(sb);
return null; return null;
} }

4
src/Windows/Avalonia.Win32/Input/WindowsKeyboardDevice.cs

@ -49,7 +49,7 @@ namespace Avalonia.Win32.Input
public string StringFromVirtualKey(uint virtualKey) public string StringFromVirtualKey(uint virtualKey)
{ {
StringBuilder result = new StringBuilder(256); var result = StringBuilderCache.Acquire(256);
int length = UnmanagedMethods.ToUnicode( int length = UnmanagedMethods.ToUnicode(
virtualKey, virtualKey,
0, 0,
@ -57,7 +57,7 @@ namespace Avalonia.Win32.Input
result, result,
256, 256,
0); 0);
return result.ToString(); return StringBuilderCache.GetStringAndRelease(result);
} }
private void UpdateKeyStates() private void UpdateKeyStates()

4
src/Windows/Avalonia.Win32/OleDataObject.cs

@ -103,11 +103,11 @@ namespace Avalonia.Win32
for (int i = 0; i < fileCount; i++) for (int i = 0; i < fileCount; i++)
{ {
int pathLen = UnmanagedMethods.DragQueryFile(hGlobal, i, null, 0); int pathLen = UnmanagedMethods.DragQueryFile(hGlobal, i, null, 0);
StringBuilder sb = new StringBuilder(pathLen+1); var sb = StringBuilderCache.Acquire(pathLen+1);
if (UnmanagedMethods.DragQueryFile(hGlobal, i, sb, sb.Capacity) == pathLen) if (UnmanagedMethods.DragQueryFile(hGlobal, i, sb, sb.Capacity) == pathLen)
{ {
files.Add(sb.ToString()); files.Add(StringBuilderCache.GetStringAndRelease(sb));
} }
} }
} }

1
src/tools/Avalonia.Designer.HostApp/Avalonia.Designer.HostApp.csproj

@ -16,6 +16,7 @@
<ItemGroup> <ItemGroup>
<Compile Include="..\..\..\src\Markup\Avalonia.Markup.Xaml.Loader\CompilerExtensions\**\*.cs" /> <Compile Include="..\..\..\src\Markup\Avalonia.Markup.Xaml.Loader\CompilerExtensions\**\*.cs" />
<Compile Include="..\..\..\src\Markup\Avalonia.Markup.Xaml.Loader\AvaloniaXamlIlRuntimeCompiler.cs" /> <Compile Include="..\..\..\src\Markup\Avalonia.Markup.Xaml.Loader\AvaloniaXamlIlRuntimeCompiler.cs" />
<Compile Include="..\..\Avalonia.Base\StringBuilderCache.cs" Link="StringBuilderCache.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Avalonia.Angle.Windows.Natives" Version="2.1.0.2020091801" /> <PackageReference Include="Avalonia.Angle.Windows.Natives" Version="2.1.0.2020091801" />

Loading…
Cancel
Save