Browse Source

Move IsOnPlatform method to the xaml helpers class

release/11.0.0-preview3
Max Katz 4 years ago
parent
commit
06a68751a4
  1. 3
      samples/ControlCatalog/Pages/PlatformInfoPage.xaml.cs
  2. 48
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguageParseIntrinsics.cs
  3. 46
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlOnPlatformTransformer.cs
  4. 11
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs
  5. 18
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/OnPlatformExtension.cs
  6. 28
      src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs
  7. 30
      tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/OnPlatformExtensionTests.cs

3
samples/ControlCatalog/Pages/PlatformInfoPage.xaml.cs

@ -1,5 +1,4 @@
using Avalonia; using Avalonia.Controls;
using Avalonia.Controls;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using ControlCatalog.ViewModels; using ControlCatalog.ViewModels;

48
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguageParseIntrinsics.cs

@ -48,10 +48,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
try try
{ {
var thickness = Thickness.Parse(text); var thickness = Thickness.Parse(text);
result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Thickness, types.ThicknessFullConstructor, result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Thickness, types.ThicknessFullConstructor,
new[] { thickness.Left, thickness.Top, thickness.Right, thickness.Bottom }); new[] { thickness.Left, thickness.Top, thickness.Right, thickness.Bottom });
return true; return true;
} }
catch catch
@ -65,10 +65,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
try try
{ {
var point = Point.Parse(text); var point = Point.Parse(text);
result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Point, types.PointFullConstructor, result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Point, types.PointFullConstructor,
new[] { point.X, point.Y }); new[] { point.X, point.Y });
return true; return true;
} }
catch catch
@ -76,16 +76,16 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a point", node); throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a point", node);
} }
} }
if (type.Equals(types.Vector)) if (type.Equals(types.Vector))
{ {
try try
{ {
var vector = Vector.Parse(text); var vector = Vector.Parse(text);
result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Vector, types.VectorFullConstructor, result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Vector, types.VectorFullConstructor,
new[] { vector.X, vector.Y }); new[] { vector.X, vector.Y });
return true; return true;
} }
catch catch
@ -93,16 +93,16 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a vector", node); throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a vector", node);
} }
} }
if (type.Equals(types.Size)) if (type.Equals(types.Size))
{ {
try try
{ {
var size = Size.Parse(text); var size = Size.Parse(text);
result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Size, types.SizeFullConstructor, result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Size, types.SizeFullConstructor,
new[] { size.Width, size.Height }); new[] { size.Width, size.Height });
return true; return true;
} }
catch catch
@ -110,16 +110,16 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a size", node); throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a size", node);
} }
} }
if (type.Equals(types.Matrix)) if (type.Equals(types.Matrix))
{ {
try try
{ {
var matrix = Matrix.Parse(text); var matrix = Matrix.Parse(text);
result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Matrix, types.MatrixFullConstructor, result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Matrix, types.MatrixFullConstructor,
new[] { matrix.M11, matrix.M12, matrix.M21, matrix.M22, matrix.M31, matrix.M32 }); new[] { matrix.M11, matrix.M12, matrix.M21, matrix.M22, matrix.M31, matrix.M32 });
return true; return true;
} }
catch catch
@ -127,16 +127,16 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a matrix", node); throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a matrix", node);
} }
} }
if (type.Equals(types.CornerRadius)) if (type.Equals(types.CornerRadius))
{ {
try try
{ {
var cornerRadius = CornerRadius.Parse(text); var cornerRadius = CornerRadius.Parse(text);
result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.CornerRadius, types.CornerRadiusFullConstructor, result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.CornerRadius, types.CornerRadiusFullConstructor,
new[] { cornerRadius.TopLeft, cornerRadius.TopRight, cornerRadius.BottomRight, cornerRadius.BottomLeft }); new[] { cornerRadius.TopLeft, cornerRadius.TopRight, cornerRadius.BottomRight, cornerRadius.BottomLeft });
return true; return true;
} }
catch catch
@ -144,7 +144,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a corner radius", node); throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a corner radius", node);
} }
} }
if (type.Equals(types.Color)) if (type.Equals(types.Color))
{ {
if (!Color.TryParse(text, out Color color)) if (!Color.TryParse(text, out Color color))
@ -165,9 +165,9 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
try try
{ {
var relativePoint = RelativePoint.Parse(text); var relativePoint = RelativePoint.Parse(text);
var relativePointTypeRef = new XamlAstClrTypeReference(node, types.RelativePoint, false); var relativePointTypeRef = new XamlAstClrTypeReference(node, types.RelativePoint, false);
result = new XamlAstNewClrObjectNode(node, relativePointTypeRef, types.RelativePointFullConstructor, new List<IXamlAstValueNode> result = new XamlAstNewClrObjectNode(node, relativePointTypeRef, types.RelativePointFullConstructor, new List<IXamlAstValueNode>
{ {
new XamlConstantNode(node, types.XamlIlTypes.Double, relativePoint.Point.X), new XamlConstantNode(node, types.XamlIlTypes.Double, relativePoint.Point.X),
@ -188,9 +188,9 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
try try
{ {
var gridLength = GridLength.Parse(text); var gridLength = GridLength.Parse(text);
result = new AvaloniaXamlIlGridLengthAstNode(node, types, gridLength); result = new AvaloniaXamlIlGridLengthAstNode(node, types, gridLength);
return true; return true;
} }
catch catch
@ -201,12 +201,12 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
if (type.Equals(types.Cursor)) if (type.Equals(types.Cursor))
{ {
if (TypeSystemHelpers.TryGetEnumValueNode(types.StandardCursorType, text, node, out var enumConstantNode)) if (TypeSystemHelpers.TryGetEnumValueNode(types.StandardCursorType, text, node, false, out var enumConstantNode))
{ {
var cursorTypeRef = new XamlAstClrTypeReference(node, types.Cursor, false); var cursorTypeRef = new XamlAstClrTypeReference(node, types.Cursor, false);
result = new XamlAstNewClrObjectNode(node, cursorTypeRef, types.CursorTypeConstructor, new List<IXamlAstValueNode> { enumConstantNode }); result = new XamlAstNewClrObjectNode(node, cursorTypeRef, types.CursorTypeConstructor, new List<IXamlAstValueNode> { enumConstantNode });
return true; return true;
} }
} }
@ -275,7 +275,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
} }
private static bool ConvertDefinitionList( private static bool ConvertDefinitionList(
IXamlAstValueNode node, IXamlAstValueNode node,
string text, string text,
AvaloniaXamlIlWellKnownTypes types, AvaloniaXamlIlWellKnownTypes types,
IXamlType listType, IXamlType listType,

46
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlOnPlatformTransformer.cs

@ -37,7 +37,7 @@ internal class AvaloniaXamlIlOnPlatformTransformer : IXamlAstTransformer
} }
IXamlAstNode defaultValue = null; IXamlAstNode defaultValue = null;
var values = new Dictionary<string, IXamlAstNode>(); var values = new Dictionary<XamlConstantNode, IXamlAstNode>();
var directives = objectNode.Children.OfType<XamlAstXmlDirective>().ToArray(); var directives = objectNode.Children.OfType<XamlAstXmlDirective>().ToArray();
@ -75,23 +75,22 @@ internal class AvaloniaXamlIlOnPlatformTransformer : IXamlAstTransformer
foreach (var platform in platformStr.Split(new[] { ',' }, foreach (var platform in platformStr.Split(new[] { ',' },
StringSplitOptions.RemoveEmptyEntries)) StringSplitOptions.RemoveEmptyEntries))
{ {
values.Add(platform.Trim().ToUpperInvariant(), transformed); values.Add(ConvertPlatformNode(platform.Trim().ToUpperInvariant(), onObj), transformed);
} }
} }
} }
else else
{ {
var platformStr = extProp.Property.GetClrProperty().Name.Trim().ToUpperInvariant(); var platformStr = extProp.Property.GetClrProperty().Name.Trim().ToUpperInvariant();
var transformed = TransformNode(targetPropertyNode.Property, extProp.Values, var transformed = TransformNode(targetPropertyNode.Property, extProp.Values,
typeArgument, directives, extProp); typeArgument, directives, extProp);
if (platformStr.Equals("default", StringComparison.OrdinalIgnoreCase)) if (platformStr.Equals("DEFAULT", StringComparison.OrdinalIgnoreCase))
{ {
defaultValue = transformed; defaultValue = transformed;
} }
else else if (platformStr != "CONTENT")
{ {
values.Add(platformStr, transformed); values.Add(ConvertPlatformNode(platformStr, extProp), transformed);
} }
} }
} }
@ -104,6 +103,26 @@ internal class AvaloniaXamlIlOnPlatformTransformer : IXamlAstTransformer
return node; return node;
XamlConstantNode ConvertPlatformNode(string platform, IXamlLineInfo li)
{
var osTypeEnum = context.GetAvaloniaTypes().OperatingSystemType;
if (platform.Equals("MACOS", StringComparison.OrdinalIgnoreCase))
{
platform = "OSX";
}
if (platform.Equals("WINDOWS", StringComparison.OrdinalIgnoreCase))
{
platform = "WINNT";
}
if (TypeSystemHelpers.TryGetEnumValueNode(osTypeEnum, platform, li, true, out var enumConstantNode))
{
return enumConstantNode;
}
throw new XamlParseException($"Unable to parse platform name: \"{platform}\"", li);
}
XamlAstXamlPropertyValueNode TransformNode( XamlAstXamlPropertyValueNode TransformNode(
IXamlAstPropertyReference property, IXamlAstPropertyReference property,
IReadOnlyCollection<IXamlAstValueNode> values, IReadOnlyCollection<IXamlAstValueNode> values,
@ -140,11 +159,11 @@ internal class AvaloniaXamlIlOnPlatformTransformer : IXamlAstTransformer
{ {
private IXamlAstNode _defaultValue; private IXamlAstNode _defaultValue;
private readonly IXamlAstNode[] _values; private readonly IXamlAstNode[] _values;
private readonly string[] _valuePlatforms; private readonly XamlConstantNode[] _valuePlatforms;
public XamlIlOnPlatformExtensionNode( public XamlIlOnPlatformExtensionNode(
IXamlAstNode defaultValue, IXamlAstNode defaultValue,
IDictionary<string, IXamlAstNode> values, IDictionary<XamlConstantNode, IXamlAstNode> values,
IXamlAstTypeReference targetType, IXamlAstTypeReference targetType,
IXamlLineInfo info) : base(info) IXamlLineInfo info) : base(info)
{ {
@ -158,6 +177,7 @@ internal class AvaloniaXamlIlOnPlatformTransformer : IXamlAstTransformer
{ {
_defaultValue = _defaultValue?.Visit(visitor); _defaultValue = _defaultValue?.Visit(visitor);
VisitList(_values, visitor); VisitList(_values, visitor);
VisitList(_valuePlatforms, visitor);
} }
public IXamlAstTypeReference Type { get; } public IXamlAstTypeReference Type { get; }
@ -165,11 +185,8 @@ internal class AvaloniaXamlIlOnPlatformTransformer : IXamlAstTransformer
public XamlILNodeEmitResult Emit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, public XamlILNodeEmitResult Emit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context,
IXamlILEmitter codeGen) IXamlILEmitter codeGen)
{ {
var operatingSystemClass = var osTypeEnum = context.GetAvaloniaTypes().OperatingSystemType;
context.Configuration.TypeSystem.GetType( var isOSPlatformMethod = context.GetAvaloniaTypes().IsOnPlatformMethod;
"Avalonia.Markup.Xaml.MarkupExtensions.OnPlatformExtensionHelper");
var isOSPlatformMethod = operatingSystemClass
.FindMethod(m => m.IsStatic && m.Parameters.Count == 1 && m.Name == "IsOSPlatform");
var ret = codeGen.DefineLabel(); var ret = codeGen.DefineLabel();
@ -179,7 +196,8 @@ internal class AvaloniaXamlIlOnPlatformTransformer : IXamlAstTransformer
var propertyNode = _values[index]; var propertyNode = _values[index];
var next = codeGen.DefineLabel(); var next = codeGen.DefineLabel();
codeGen.Ldstr(platform); codeGen.Ldloc(context.ContextLocal);
context.Emit(platform, codeGen, osTypeEnum);
codeGen.EmitCall(isOSPlatformMethod); codeGen.EmitCall(isOSPlatformMethod);
codeGen.Brfalse(next); codeGen.Brfalse(next);
context.Emit(propertyNode, codeGen, null); context.Emit(propertyNode, codeGen, null);

11
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs

@ -9,6 +9,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{ {
class AvaloniaXamlIlWellKnownTypes class AvaloniaXamlIlWellKnownTypes
{ {
public IXamlType RuntimeHelpers { get; }
public IXamlType AvaloniaObject { get; } public IXamlType AvaloniaObject { get; }
public IXamlType IAvaloniaObject { get; } public IXamlType IAvaloniaObject { get; }
public IXamlType BindingPriority { get; } public IXamlType BindingPriority { get; }
@ -102,8 +103,13 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
public IXamlType ResourceDictionary { get; } public IXamlType ResourceDictionary { get; }
public IXamlMethod ResourceDictionaryDeferredAdd { get; } public IXamlMethod ResourceDictionaryDeferredAdd { get; }
public IXamlType OperatingSystemType { get; }
public IXamlMethod IsOnPlatformMethod { get; }
public AvaloniaXamlIlWellKnownTypes(TransformerConfiguration cfg) public AvaloniaXamlIlWellKnownTypes(TransformerConfiguration cfg)
{ {
RuntimeHelpers = cfg.TypeSystem.GetType("Avalonia.Markup.Xaml.XamlIl.Runtime.XamlIlRuntimeHelpers");
XamlIlTypes = cfg.WellKnownTypes; XamlIlTypes = cfg.WellKnownTypes;
AvaloniaObject = cfg.TypeSystem.GetType("Avalonia.AvaloniaObject"); AvaloniaObject = cfg.TypeSystem.GetType("Avalonia.AvaloniaObject");
IAvaloniaObject = cfg.TypeSystem.GetType("Avalonia.IAvaloniaObject"); IAvaloniaObject = cfg.TypeSystem.GetType("Avalonia.IAvaloniaObject");
@ -227,6 +233,9 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
cfg.TypeSystem.GetType("System.Func`2").MakeGenericType( cfg.TypeSystem.GetType("System.Func`2").MakeGenericType(
cfg.TypeSystem.GetType("System.IServiceProvider"), cfg.TypeSystem.GetType("System.IServiceProvider"),
XamlIlTypes.Object)); XamlIlTypes.Object));
OperatingSystemType = cfg.TypeSystem.GetType("Avalonia.Platform.OperatingSystemType");
IsOnPlatformMethod = RuntimeHelpers.FindMethod(m => m.IsStatic && m.Parameters.Count == 2 && m.Name == "IsOnPlatform");
} }
} }
@ -239,7 +248,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
ctx.SetItem(rv = new AvaloniaXamlIlWellKnownTypes(ctx.Configuration)); ctx.SetItem(rv = new AvaloniaXamlIlWellKnownTypes(ctx.Configuration));
return rv; return rv;
} }
public static AvaloniaXamlIlWellKnownTypes GetAvaloniaTypes(this XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> ctx) public static AvaloniaXamlIlWellKnownTypes GetAvaloniaTypes(this XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> ctx)
{ {
if (ctx.TryGetItem<AvaloniaXamlIlWellKnownTypes>(out var rv)) if (ctx.TryGetItem<AvaloniaXamlIlWellKnownTypes>(out var rv))

18
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/OnPlatformExtension.cs

@ -1,30 +1,12 @@
#nullable enable #nullable enable
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices;
using Avalonia.Metadata; using Avalonia.Metadata;
using Avalonia.Platform; using Avalonia.Platform;
namespace Avalonia.Markup.Xaml.MarkupExtensions; namespace Avalonia.Markup.Xaml.MarkupExtensions;
public static class OnPlatformExtensionHelper
{
// TEMPORARY, to replace with XAML compiler namespace helpers
public static bool IsOSPlatform(string platform)
{
var runtimeInfo = AvaloniaLocator.Current.GetRequiredService<IRuntimePlatform>().GetRuntimeInfo();
return platform switch
{
"WINDOWS" => runtimeInfo.OperatingSystem == OperatingSystemType.WinNT,
"MACOS" => runtimeInfo.OperatingSystem == OperatingSystemType.OSX,
_ => runtimeInfo.OperatingSystem.ToString().Equals(platform, StringComparison.OrdinalIgnoreCase)
};
//return RuntimeInformation.IsOSPlatform(OSPlatform.Create(platform));
}
}
public class On public class On
{ {
public string Platform { get; set; } = "Unknown"; public string Platform { get; set; } = "Unknown";

28
src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs

@ -1,11 +1,12 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.Templates; using Avalonia.Controls.Templates;
using Avalonia.Data; using Avalonia.Data;
using Avalonia.Platform;
// ReSharper disable UnusedMember.Global // ReSharper disable UnusedMember.Global
// ReSharper disable UnusedParameter.Global // ReSharper disable UnusedParameter.Global
@ -18,7 +19,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.Runtime
{ {
return DeferredTransformationFactoryV2<IControl>(builder, provider); return DeferredTransformationFactoryV2<IControl>(builder, provider);
} }
public static Func<IServiceProvider, object> DeferredTransformationFactoryV2<T>(Func<IServiceProvider, object> builder, public static Func<IServiceProvider, object> DeferredTransformationFactoryV2<T>(Func<IServiceProvider, object> builder,
IServiceProvider provider) IServiceProvider provider)
{ {
@ -31,7 +32,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.Runtime
var scope = parentScope != null ? new ChildNameScope(parentScope) : (INameScope)new NameScope(); var scope = parentScope != null ? new ChildNameScope(parentScope) : (INameScope)new NameScope();
var obj = builder(new DeferredParentServiceProvider(sp, resourceNodes, rootObject, scope)); var obj = builder(new DeferredParentServiceProvider(sp, resourceNodes, rootObject, scope));
scope.Complete(); scope.Complete();
if(typeof(T) == typeof(IControl)) if(typeof(T) == typeof(IControl))
return new ControlTemplateResult((IControl)obj, scope); return new ControlTemplateResult((IControl)obj, scope);
@ -107,9 +108,9 @@ namespace Avalonia.Markup.Xaml.XamlIl.Runtime
throw new ArgumentException("Don't know what to do with " + value.GetType()); throw new ArgumentException("Don't know what to do with " + value.GetType());
} }
public static IServiceProvider CreateInnerServiceProviderV1(IServiceProvider compiled) public static IServiceProvider CreateInnerServiceProviderV1(IServiceProvider compiled)
=> new InnerServiceProvider(compiled); => new InnerServiceProvider(compiled);
class InnerServiceProvider : IServiceProvider class InnerServiceProvider : IServiceProvider
{ {
private readonly IServiceProvider _compiledProvider; private readonly IServiceProvider _compiledProvider;
@ -136,7 +137,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.Runtime
{ {
_nsInfo = nsInfo; _nsInfo = nsInfo;
} }
public Type Resolve(string qualifiedTypeName) public Type Resolve(string qualifiedTypeName)
{ {
var sp = qualifiedTypeName.Split(new[] {':'}, 2); var sp = qualifiedTypeName.Split(new[] {':'}, 2);
@ -166,23 +167,27 @@ namespace Avalonia.Markup.Xaml.XamlIl.Runtime
return new RootServiceProvider(new NameScope()); return new RootServiceProvider(new NameScope());
} }
#line default #line default
class RootServiceProvider : IServiceProvider, IAvaloniaXamlIlParentStackProvider class RootServiceProvider : IServiceProvider, IAvaloniaXamlIlParentStackProvider
{ {
private readonly INameScope _nameScope; private readonly INameScope _nameScope;
private readonly IRuntimePlatform _runtimePlatform;
public RootServiceProvider(INameScope nameScope) public RootServiceProvider(INameScope nameScope)
{ {
_nameScope = nameScope; _nameScope = nameScope;
_runtimePlatform = AvaloniaLocator.Current.GetRequiredService<IRuntimePlatform>();
} }
public object GetService(Type serviceType) public object GetService(Type serviceType)
{ {
if (serviceType == typeof(INameScope)) if (serviceType == typeof(INameScope))
return _nameScope; return _nameScope;
if (serviceType == typeof(IAvaloniaXamlIlParentStackProvider)) if (serviceType == typeof(IAvaloniaXamlIlParentStackProvider))
return this; return this;
if (serviceType == typeof(IRuntimePlatform))
return _runtimePlatform;
return null; return null;
} }
@ -195,5 +200,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.Runtime
} }
} }
} }
public static bool IsOnPlatform(IServiceProvider serviceProvider, OperatingSystemType platform)
{
return serviceProvider.GetService<IRuntimePlatform>().GetRuntimeInfo().OperatingSystem == platform;
}
} }
} }

30
tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/OnPlatformExtensionTests.cs

@ -1,7 +1,4 @@
using System; using Avalonia.Controls;
using System.Globalization;
using Avalonia.Controls;
using Avalonia.Data.Converters;
using Avalonia.Media; using Avalonia.Media;
using Avalonia.Platform; using Avalonia.Platform;
using Xunit; using Xunit;
@ -330,6 +327,31 @@ public class OnPlatformExtensionTests : XamlTestBase
} }
} }
[Fact]
public void BindingExtension_Works_Inside_Of_OnPlatform()
{
using (AvaloniaLocator.EnterScope())
{
AvaloniaLocator.CurrentMutable.Bind<IRuntimePlatform>()
.ToConstant(new TestRuntimePlatform(OperatingSystemType.WinNT));
var xaml = @"
<UserControl xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
<UserControl.Resources>
<x:String x:Key='text'>foobar</x:String>
</UserControl.Resources>
<TextBlock Name='textBlock' Text='{OnPlatform Windows={CompiledBinding Source={StaticResource text}}}'/>
</UserControl>";
var window = (UserControl)AvaloniaRuntimeXamlLoader.Load(xaml);
var textBlock = window.FindControl<TextBlock>("textBlock");
Assert.Equal("foobar", textBlock.Text);
}
}
private class TestRuntimePlatform : StandardRuntimePlatform private class TestRuntimePlatform : StandardRuntimePlatform
{ {
private readonly OperatingSystemType _operatingSystemType; private readonly OperatingSystemType _operatingSystemType;

Loading…
Cancel
Save