public static bool TryGetEnumValueNode(IXamlIlType enumType, string value, IXamlIlLineInfo lineInfo, out XamlIlConstantNode rv) { if (TryGetEnumValue(enumType, value, out var constant)) { rv = new XamlIlConstantNode(lineInfo, enumType, constant); return(true); } rv = null; return(false); }
public static bool ParseConstantIfTypeAllows(string s, IXamlIlType type, IXamlIlLineInfo info, out XamlIlConstantNode rv) { rv = null; if (type.Namespace != "System") { return(false); } object Parse() { if (type.Name == "Byte") { return(byte.Parse(s, CultureInfo.InvariantCulture)); } if (type.Name == "SByte") { return(sbyte.Parse(s, CultureInfo.InvariantCulture)); } if (type.Name == "Int16") { return(Int16.Parse(s, CultureInfo.InvariantCulture)); } if (type.Name == "UInt16") { return(UInt16.Parse(s, CultureInfo.InvariantCulture)); } if (type.Name == "Int32") { return(Int32.Parse(s, CultureInfo.InvariantCulture)); } if (type.Name == "UInt32") { return(UInt32.Parse(s, CultureInfo.InvariantCulture)); } if (type.Name == "Int64") { return(Int64.Parse(s, CultureInfo.InvariantCulture)); } if (type.Name == "UInt64") { return(UInt64.Parse(s, CultureInfo.InvariantCulture)); } if (type.Name == "Single") { return(Single.Parse(s, CultureInfo.InvariantCulture)); } if (type.Name == "Double") { return(Double.Parse(s, CultureInfo.InvariantCulture)); } if (type.Name == "Boolean") { return(Boolean.Parse(s)); } return(null); } var r = Parse(); if (r != null) { rv = new XamlIlConstantNode(info, type, r); return(true); } return(false); }
public static bool TryConvertValue(XamlIlAstTransformationContext context, IXamlIlAstValueNode node, IXamlIlType type, out IXamlIlAstValueNode 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 XamlIlAstTextNode tn) { if (type.IsEnum) { var enumValue = type.Fields.FirstOrDefault(f => f.Name == tn.Text); if (enumValue == null && !string.IsNullOrWhiteSpace(tn.Text) && long.TryParse(tn.Text, out var parsed)) { var enumTypeName = type.GetEnumUnderlyingType().Name; var obj = enumTypeName == "Int32" || enumTypeName == "UInt32" ? unchecked ((int)parsed) : (object)parsed; rv = new XamlIlConstantNode(node, type, obj); return(true); } if (enumValue != null) { rv = TypeSystemHelpers.GetLiteralFieldConstantNode(enumValue, node); 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 = XamlIlTypeReferenceResolver.ResolveType(context, tn.Text, false, tn, true); rv = new XamlIlTypeExtensionNode(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 XamlIlLoadMethodDelegateNode(tn, context.RootObject, type, handler); return(true); } } } IXamlIlAstValueNode CreateInvariantCulture() => new XamlIlStaticOrTargetedReturnMethodCallNode(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 <IXamlIlAstValueNode> { node }; if (parser.Parameters.Count == 2) { args.Add(CreateInvariantCulture()); } rv = new XamlIlStaticOrTargetedReturnMethodCallNode(node, parser, args); return(true); } if (cfg.TypeMappings.TypeDescriptorContext != null) { var typeConverterAttribute = cfg.GetCustomAttribute(type, cfg.TypeMappings.TypeConverterAttributes).FirstOrDefault(); if (typeConverterAttribute != null) { var arg = typeConverterAttribute.Parameters.FirstOrDefault(); var converterType = (arg as IXamlIlType) ?? (arg is String sarg ? cfg.TypeSystem.FindType(sarg) : null); if (converterType != null) { var converterMethod = converterType.FindMethod("ConvertFrom", cfg.WellKnownTypes.Object, false, cfg.TypeMappings.TypeDescriptorContext, cfg.WellKnownTypes.CultureInfo, cfg.WellKnownTypes.Object); rv = new XamlIlAstNeedsParentStackValueNode(node, new XamlIlAstRuntimeCastNode(node, new XamlIlStaticOrTargetedReturnMethodCallNode(node, converterMethod, new[] { new XamlIlAstNewClrObjectNode(node, new XamlIlAstClrTypeReference(node, converterType, false), null, new List <IXamlIlAstValueNode>()), new XamlIlAstContextLocalNode(node, cfg.TypeMappings.TypeDescriptorContext), CreateInvariantCulture(), node }), new XamlIlAstClrTypeReference(node, type, false))); return(true); } } } return(false); }