public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { var sourceType = value.GetType(); if (sourceType == pointType) { return(value); } if (sourceType == typeof(string)) { return(ConvertFrom(context, culture, Symbol.FromString((string)value))); } if (sourceType == typeof(Symbol)) { var symbol = (Symbol)value; try { var symbols = symbol.AsSymbols; var fields = symbols .Select((fieldSymbol, index) => { var fieldName = "Item" + (index + 1); var fieldProperty = pointType.GetProperty(fieldName, BindingFlags.Public | BindingFlags.Instance); var fieldConverter = new SymbolicConverter(fieldProperty.PropertyType); var fieldValue = fieldSymbol.Match( atom => fieldConverter.ConvertFromString(atom), number => fieldConverter.ConvertFromString(number), str => fieldConverter.ConvertFromString(SymbolParser.Explicitize(str)), _ => fieldSymbol, _ => fieldConverter.ConvertFrom(fieldSymbol)); return(fieldValue); }) .ToArray(); return(Activator.CreateInstance(pointType, fields)); } catch (Exception exn) { throw new ArgumentException($"Invalid form '{symbol}' for {value.GetType().FullName}. Required form is '[Value ...]'.", exn); } } return(base.ConvertFrom(context, culture, value)); }
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { var sourceType = value.GetType(); if (sourceType == pointType) { return(value); } if (sourceType == typeof(string)) { return(ConvertFrom(context, culture, Symbol.FromString((string)value))); } if (sourceType == typeof(Symbol)) { var symbol = (Symbol)value; try { var fields = symbol.AsSymbols; var tagField = pointType.GetField(nameof(Union <bool, bool> .Tag)); var tagConverter = new SymbolicConverter(tagField.FieldType); var tag = (Enum)tagConverter.ConvertFromString(fields[0].AsAtom); var dataField = pointType.GetField(nameof(Union <bool, bool> .Data)); var dataConverter = new SymbolicConverter(tag.TryGetAttributeOfType <UnionAttribute>().TryThen(attr => attr.Type) ?? dataField.FieldType); var data = fields[1].Match( atom => dataConverter.ConvertFromString(atom), number => dataConverter.ConvertFromString(number), str => dataConverter.ConvertFromString(SymbolParser.Explicitize(str)), _ => fields[1], _ => dataConverter.ConvertFrom(fields[1])); return(Activator.CreateInstance(pointType, new object[] { tag, data })); } catch (Exception exn) { throw new ArgumentException($"Invalid form '{symbol}' for {value.GetType().FullName}. Required form is '[Enum Value]'.", exn); } } return(base.ConvertFrom(context, culture, value)); }