コード例 #1
0
        public static bool CustomValueConverter(AstTransformationContext context,
                                                IXamlAstValueNode node, IXamlType type, out IXamlAstValueNode result)
        {
            if (type.FullName == "System.TimeSpan" &&
                node is XamlAstTextNode tn &&
                !tn.Text.Contains(":"))
            {
                var seconds = double.Parse(tn.Text, CultureInfo.InvariantCulture);
                result = new XamlStaticOrTargetedReturnMethodCallNode(tn,
                                                                      type.FindMethod("FromSeconds", type, false, context.Configuration.WellKnownTypes.Double),
                                                                      new[]
                {
                    new XamlConstantNode(tn, context.Configuration.WellKnownTypes.Double, seconds)
                });
                return(true);
            }

            if (type.FullName == "Avalonia.AvaloniaProperty")
            {
                var scope = context.ParentNodes().OfType <AvaloniaXamlIlTargetTypeMetadataNode>().FirstOrDefault();
                if (scope == null)
                {
                    throw new XamlX.XamlLoadException("Unable to find the parent scope for AvaloniaProperty lookup", node);
                }
                if (!(node is XamlAstTextNode text))
                {
                    throw new XamlX.XamlLoadException("Property should be a text node", node);
                }
                result = XamlIlAvaloniaPropertyHelper.CreateNode(context, text.Text, scope.TargetType, text);
                return(true);
            }

            result = null;
            return(false);
        }
コード例 #2
0
        public static bool CustomValueConverter(AstTransformationContext context,
                                                IXamlAstValueNode node, IXamlType type, out IXamlAstValueNode result)
        {
            if (!(node is XamlAstTextNode textNode))
            {
                result = null;
                return(false);
            }

            var text = textNode.Text;

            var types = context.GetAvaloniaTypes();

            if (type.FullName == "System.TimeSpan")
            {
                var tsText = text.Trim();

                if (!TimeSpan.TryParse(tsText, CultureInfo.InvariantCulture, out var timeSpan))
                {
                    // // shorthand seconds format (ie. "0.25")
                    if (!tsText.Contains(":") && double.TryParse(tsText,
                                                                 NumberStyles.Float | NumberStyles.AllowThousands,
                                                                 CultureInfo.InvariantCulture, out var seconds))
                    {
                        timeSpan = TimeSpan.FromSeconds(seconds);
                    }
                    else
                    {
                        throw new XamlX.XamlLoadException($"Unable to parse {text} as a time span", node);
                    }
                }


                result = new XamlStaticOrTargetedReturnMethodCallNode(node,
                                                                      type.FindMethod("FromTicks", type, false, types.Long),
                                                                      new[] { new XamlConstantNode(node, types.Long, timeSpan.Ticks) });
                return(true);
            }

            if (type.Equals(types.FontFamily))
            {
                result = new AvaloniaXamlIlFontFamilyAstNode(types, text, node);
                return(true);
            }

            if (type.FullName == "Avalonia.AvaloniaProperty")
            {
                var scope = context.ParentNodes().OfType <AvaloniaXamlIlTargetTypeMetadataNode>().FirstOrDefault();
                if (scope == null)
                {
                    throw new XamlX.XamlLoadException("Unable to find the parent scope for AvaloniaProperty lookup", node);
                }

                result = XamlIlAvaloniaPropertyHelper.CreateNode(context, text, scope.TargetType, node);
                return(true);
            }

            result = null;
            return(false);
        }
        public static bool TryConvert(AstTransformationContext context, IXamlAstValueNode node, string text, IXamlType type, AvaloniaXamlIlWellKnownTypes types, out IXamlAstValueNode result)
        {
            if (type.FullName == "System.TimeSpan")
            {
                var tsText = text.Trim();

                if (!TimeSpan.TryParse(tsText, CultureInfo.InvariantCulture, out var timeSpan))
                {
                    // // shorthand seconds format (ie. "0.25")
                    if (!tsText.Contains(":") && double.TryParse(tsText,
                                                                 NumberStyles.Float | NumberStyles.AllowThousands,
                                                                 CultureInfo.InvariantCulture, out var seconds))
                    {
                        timeSpan = TimeSpan.FromSeconds(seconds);
                    }
                    else
                    {
                        throw new XamlX.XamlLoadException($"Unable to parse {text} as a time span", node);
                    }
                }

                result = new XamlStaticOrTargetedReturnMethodCallNode(node,
                                                                      type.FindMethod("FromTicks", type, false, types.Long),
                                                                      new[] { new XamlConstantNode(node, types.Long, timeSpan.Ticks) });
                return(true);
            }

            if (type.Equals(types.FontFamily))
            {
                result = new AvaloniaXamlIlFontFamilyAstNode(types, text, node);
                return(true);
            }

            if (type.Equals(types.Thickness))
            {
                try
                {
                    var thickness = Thickness.Parse(text);

                    result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Thickness, types.ThicknessFullConstructor,
                                                                         new[] { thickness.Left, thickness.Top, thickness.Right, thickness.Bottom });

                    return(true);
                }
                catch
                {
                    throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a thickness", node);
                }
            }

            if (type.Equals(types.Point))
            {
                try
                {
                    var point = Point.Parse(text);

                    result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Point, types.PointFullConstructor,
                                                                         new[] { point.X, point.Y });

                    return(true);
                }
                catch
                {
                    throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a point", node);
                }
            }

            if (type.Equals(types.Vector))
            {
                try
                {
                    var vector = Vector.Parse(text);

                    result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Vector, types.VectorFullConstructor,
                                                                         new[] { vector.X, vector.Y });

                    return(true);
                }
                catch
                {
                    throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a vector", node);
                }
            }

            if (type.Equals(types.Size))
            {
                try
                {
                    var size = Size.Parse(text);

                    result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Size, types.SizeFullConstructor,
                                                                         new[] { size.Width, size.Height });

                    return(true);
                }
                catch
                {
                    throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a size", node);
                }
            }

            if (type.Equals(types.Matrix))
            {
                try
                {
                    var matrix = Matrix.Parse(text);

                    result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Matrix, types.MatrixFullConstructor,
                                                                         new[] { matrix.M11, matrix.M12, matrix.M21, matrix.M22, matrix.M31, matrix.M32 });

                    return(true);
                }
                catch
                {
                    throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a matrix", node);
                }
            }

            if (type.Equals(types.CornerRadius))
            {
                try
                {
                    var cornerRadius = CornerRadius.Parse(text);

                    result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.CornerRadius, types.CornerRadiusFullConstructor,
                                                                         new[] { cornerRadius.TopLeft, cornerRadius.TopRight, cornerRadius.BottomRight, cornerRadius.BottomLeft });

                    return(true);
                }
                catch
                {
                    throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a corner radius", node);
                }
            }

            if (type.Equals(types.Color))
            {
                if (!Color.TryParse(text, out Color color))
                {
                    throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a color", node);
                }

                result = new XamlStaticOrTargetedReturnMethodCallNode(node,
                                                                      type.GetMethod(
                                                                          new FindMethodMethodSignature("FromUInt32", type, types.UInt)
                {
                    IsStatic = true
                }),
                                                                      new[] { new XamlConstantNode(node, types.UInt, color.ToUint32()) });

                return(true);
            }

            if (type.Equals(types.GridLength))
            {
                try
                {
                    var gridLength = GridLength.Parse(text);

                    result = new AvaloniaXamlIlGridLengthAstNode(node, types, gridLength);

                    return(true);
                }
                catch
                {
                    throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a grid length", node);
                }
            }

            if (type.Equals(types.Cursor))
            {
                if (TypeSystemHelpers.TryGetEnumValueNode(types.StandardCursorType, text, node, out var enumConstantNode))
                {
                    var cursorTypeRef = new XamlAstClrTypeReference(node, types.Cursor, false);

                    result = new XamlAstNewClrObjectNode(node, cursorTypeRef, types.CursorTypeConstructor, new List <IXamlAstValueNode> {
                        enumConstantNode
                    });

                    return(true);
                }
            }

            if (type.Equals(types.ColumnDefinitions))
            {
                return(ConvertDefinitionList(node, text, types, types.ColumnDefinitions, types.ColumnDefinition, "column definitions", out result));
            }

            if (type.Equals(types.RowDefinitions))
            {
                return(ConvertDefinitionList(node, text, types, types.RowDefinitions, types.RowDefinition, "row definitions", out result));
            }

            if (type.Equals(types.Classes))
            {
                var classes    = text.Split(' ');
                var classNodes = classes.Select(c => new XamlAstTextNode(node, c, types.XamlIlTypes.String)).ToArray();

                result = new AvaloniaXamlIlAvaloniaListConstantAstNode(node, types, types.Classes, types.XamlIlTypes.String, classNodes);
                return(true);
            }

            result = null;
            return(false);
        }
コード例 #4
0
        public static bool CustomValueConverter(AstTransformationContext context,
                                                IXamlAstValueNode node, IXamlType type, out IXamlAstValueNode result)
        {
            if (!(node is XamlAstTextNode textNode))
            {
                result = null;
                return(false);
            }

            var text = textNode.Text;

            var types = context.GetAvaloniaTypes();

            if (type.FullName == "System.TimeSpan")
            {
                var tsText = text.Trim();

                if (!TimeSpan.TryParse(tsText, CultureInfo.InvariantCulture, out var timeSpan))
                {
                    // // shorthand seconds format (ie. "0.25")
                    if (!tsText.Contains(":") && double.TryParse(tsText,
                                                                 NumberStyles.Float | NumberStyles.AllowThousands,
                                                                 CultureInfo.InvariantCulture, out var seconds))
                    {
                        timeSpan = TimeSpan.FromSeconds(seconds);
                    }
                    else
                    {
                        throw new XamlX.XamlLoadException($"Unable to parse {text} as a time span", node);
                    }
                }


                result = new XamlStaticOrTargetedReturnMethodCallNode(node,
                                                                      type.FindMethod("FromTicks", type, false, types.Long),
                                                                      new[] { new XamlConstantNode(node, types.Long, timeSpan.Ticks) });
                return(true);
            }

            if (type.Equals(types.FontFamily))
            {
                result = new AvaloniaXamlIlFontFamilyAstNode(types, text, node);
                return(true);
            }

            if (type.Equals(types.Thickness))
            {
                var thickness = Thickness.Parse(text);

                result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Thickness, types.ThicknessFullConstructor,
                                                                     new[] { thickness.Left, thickness.Top, thickness.Right, thickness.Bottom });

                return(true);
            }

            if (type.Equals(types.Point))
            {
                var point = Point.Parse(text);

                result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Point, types.PointFullConstructor,
                                                                     new[] { point.X, point.Y });

                return(true);
            }

            if (type.Equals(types.Vector))
            {
                var vector = Vector.Parse(text);

                result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Vector, types.VectorFullConstructor,
                                                                     new[] { vector.X, vector.Y });

                return(true);
            }

            if (type.Equals(types.Size))
            {
                var size = Size.Parse(text);

                result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Size, types.SizeFullConstructor,
                                                                     new[] { size.Width, size.Height });

                return(true);
            }

            if (type.Equals(types.Matrix))
            {
                var matrix = Matrix.Parse(text);

                result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Matrix, types.MatrixFullConstructor,
                                                                     new[] { matrix.M11, matrix.M12, matrix.M21, matrix.M22, matrix.M31, matrix.M32 });

                return(true);
            }

            if (type.Equals(types.CornerRadius))
            {
                var cornerRadius = CornerRadius.Parse(text);

                result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.CornerRadius, types.CornerRadiusFullConstructor,
                                                                     new[] { cornerRadius.TopLeft, cornerRadius.TopRight, cornerRadius.BottomRight, cornerRadius.BottomLeft });

                return(true);
            }

            if (type.FullName == "Avalonia.AvaloniaProperty")
            {
                var scope = context.ParentNodes().OfType <AvaloniaXamlIlTargetTypeMetadataNode>().FirstOrDefault();
                if (scope == null)
                {
                    throw new XamlX.XamlLoadException("Unable to find the parent scope for AvaloniaProperty lookup", node);
                }

                result = XamlIlAvaloniaPropertyHelper.CreateNode(context, text, scope.TargetType, node);
                return(true);
            }

            result = null;
            return(false);
        }
コード例 #5
0
        public static bool TryConvertValue(AstTransformationContext context,
                                           IXamlAstValueNode node, IXamlType type, XamlAstClrProperty propertyContext,
                                           out IXamlAstValueNode rv)
        {
            rv = null;
            var cfg = context.Configuration;

            // Since we are doing a conversion anyway, it makes sense to check for the underlying nullable type
            if (type.GenericTypeDefinition?.Equals(cfg.WellKnownTypes.NullableT) == true)
            {
                type = type.GenericArguments[0];
            }


            if (cfg.CustomValueConverter?.Invoke(context, node, type, out rv) == true)
            {
                return(true);
            }

            var nodeType = node.Type.GetClrType();

            // Implicit type converters
            if (!nodeType.Equals(cfg.WellKnownTypes.String))
            {
                return(false);
            }

            if (node is XamlAstTextNode tn)
            {
                if (type.IsEnum)
                {
                    if (TypeSystemHelpers.TryGetEnumValueNode(type, tn.Text, tn, out var enumConstantNode))
                    {
                        rv = enumConstantNode;
                        return(true);
                    }
                }

                // Well known types
                if (TypeSystemHelpers.ParseConstantIfTypeAllows(tn.Text, type, tn, out var constantNode))
                {
                    rv = constantNode;
                    return(true);
                }

                if (type.FullName == "System.Type")
                {
                    var resolvedType = TypeReferenceResolver.ResolveType(context, tn.Text, false, tn, true);
                    rv = new XamlTypeExtensionNode(tn, resolvedType, type);
                    return(true);
                }

                if (cfg.WellKnownTypes.Delegate.IsAssignableFrom(type))
                {
                    var invoke   = type.FindMethod(m => m.Name == "Invoke");
                    var rootType = context.RootObject.Type.GetClrType();
                    var handler  =
                        rootType.FindMethod(tn.Text, invoke.ReturnType, false, invoke.Parameters.ToArray());
                    if (handler != null)
                    {
                        rv = new XamlLoadMethodDelegateNode(tn, context.RootObject, type, handler);
                        return(true);
                    }
                }
            }

            IXamlAstValueNode CreateInvariantCulture() =>
            new XamlStaticOrTargetedReturnMethodCallNode(node,
                                                         cfg.WellKnownTypes.CultureInfo.Methods.First(x =>
                                                                                                      x.IsPublic && x.IsStatic && x.Name == "get_InvariantCulture"), null);

            var candidates = type.Methods.Where(m => m.Name == "Parse" &&
                                                m.ReturnType.Equals(type) &&
                                                m.Parameters.Count > 0 &&
                                                m.Parameters[0].Equals(cfg.WellKnownTypes.String)).ToList();

            // Types with parse method
            var parser = candidates.FirstOrDefault(m =>
                                                   m.Parameters.Count == 2 &&
                                                   (
                                                       m.Parameters[1].Equals(cfg.WellKnownTypes.CultureInfo) ||
                                                       m.Parameters[1].Equals(cfg.WellKnownTypes.IFormatProvider)
                                                   )
                                                   )
                         ?? candidates.FirstOrDefault(m => m.Parameters.Count == 1);

            if (parser != null)
            {
                var args = new List <IXamlAstValueNode> {
                    node
                };
                if (parser.Parameters.Count == 2)
                {
                    args.Add(CreateInvariantCulture());
                }

                rv = new XamlStaticOrTargetedReturnMethodCallNode(node, parser, args);
                return(true);
            }

            if (cfg.TypeMappings.TypeDescriptorContext != null)
            {
                IXamlType converterType = null;
                if (propertyContext?.TypeConverters.TryGetValue(type, out converterType) != true)
                {
                    var typeConverterAttribute =
                        cfg.GetCustomAttribute(type, cfg.TypeMappings.TypeConverterAttributes).FirstOrDefault();
                    if (typeConverterAttribute != null)
                    {
                        converterType = TryGetTypeConverterFromCustomAttribute(cfg, typeConverterAttribute);
                    }
                }

                if (converterType != null)
                {
                    var converterMethod = converterType.FindMethod("ConvertFrom", cfg.WellKnownTypes.Object, false,
                                                                   cfg.TypeMappings.TypeDescriptorContext, cfg.WellKnownTypes.CultureInfo,
                                                                   cfg.WellKnownTypes.Object);
                    rv = new XamlAstNeedsParentStackValueNode(node,
                                                              new XamlAstRuntimeCastNode(node,
                                                                                         new XamlStaticOrTargetedReturnMethodCallNode(node, converterMethod,
                                                                                                                                      new[]
                    {
                        new XamlAstNewClrObjectNode(node,
                                                    new XamlAstClrTypeReference(node, converterType, false), null,
                                                    new List <IXamlAstValueNode>()),
                        new XamlAstContextLocalNode(node, cfg.TypeMappings.TypeDescriptorContext),
                        CreateInvariantCulture(), node
                    }), new XamlAstClrTypeReference(node, type, false)));
                    return(true);
                }
            }

            return(false);
        }