예제 #1
0
        public static object GetValue(string fieldName, Type fieldType, MiniYaml yaml, MemberInfo field)
        {
            var value = yaml.Value;

            if (value != null)
            {
                value = value.Trim();
            }

            if (fieldType == typeof(int))
            {
                int res;
                if (Exts.TryParseIntegerInvariant(value, out res))
                {
                    return(res);
                }
                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(ushort))
            {
                ushort res;
                if (ushort.TryParse(value, NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out res))
                {
                    return(res);
                }
                return(InvalidValueAction(value, fieldType, fieldName));
            }

            if (fieldType == typeof(long))
            {
                long res;
                if (long.TryParse(value, NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out res))
                {
                    return(res);
                }
                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(float))
            {
                float res;
                if (value != null && float.TryParse(value.Replace("%", ""), NumberStyles.Float, NumberFormatInfo.InvariantInfo, out res))
                {
                    return(res * (value.Contains('%') ? 0.01f : 1f));
                }
                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(decimal))
            {
                decimal res;
                if (value != null && decimal.TryParse(value.Replace("%", ""), NumberStyles.Float, NumberFormatInfo.InvariantInfo, out res))
                {
                    return(res * (value.Contains('%') ? 0.01m : 1m));
                }
                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(string))
            {
                if (field != null && MemberHasTranslateAttribute[field] && value != null)
                {
                    return(Regex.Replace(value, "@[^@]+@", m => Translate(m.Value.Substring(1, m.Value.Length - 2)), RegexOptions.Compiled));
                }
                return(value);
            }
            else if (fieldType == typeof(Color))
            {
                Color color;
                if (value != null && HSLColor.TryParseRGB(value, out color))
                {
                    return(color);
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(Color[]))
            {
                if (value != null)
                {
                    var parts  = value.Split(',');
                    var colors = new Color[parts.Length];

                    for (var i = 0; i < colors.Length; i++)
                    {
                        if (!HSLColor.TryParseRGB(parts[i], out colors[i]))
                        {
                            return(InvalidValueAction(value, fieldType, fieldName));
                        }
                    }

                    return(colors);
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(HSLColor))
            {
                if (value != null)
                {
                    Color rgb;
                    if (HSLColor.TryParseRGB(value, out rgb))
                    {
                        return(new HSLColor(rgb));
                    }

                    // Allow old HSLColor/ColorRamp formats to be parsed as HSLColor
                    var parts = value.Split(',');
                    if (parts.Length == 3 || parts.Length == 4)
                    {
                        return(new HSLColor(
                                   (byte)Exts.ParseIntegerInvariant(parts[0]).Clamp(0, 255),
                                   (byte)Exts.ParseIntegerInvariant(parts[1]).Clamp(0, 255),
                                   (byte)Exts.ParseIntegerInvariant(parts[2]).Clamp(0, 255)));
                    }
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(Hotkey))
            {
                Hotkey res;
                if (Hotkey.TryParse(value, out res))
                {
                    return(res);
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(WDist))
            {
                WDist res;
                if (WDist.TryParse(value, out res))
                {
                    return(res);
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(WVec))
            {
                if (value != null)
                {
                    var parts = value.Split(',');
                    if (parts.Length == 3)
                    {
                        WDist rx, ry, rz;
                        if (WDist.TryParse(parts[0], out rx) && WDist.TryParse(parts[1], out ry) && WDist.TryParse(parts[2], out rz))
                        {
                            return(new WVec(rx, ry, rz));
                        }
                    }
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(WVec[]))
            {
                if (value != null)
                {
                    var parts = value.Split(',');

                    if (parts.Length % 3 != 0)
                    {
                        return(InvalidValueAction(value, fieldType, fieldName));
                    }

                    var vecs = new WVec[parts.Length / 3];

                    for (var i = 0; i < vecs.Length; ++i)
                    {
                        WDist rx, ry, rz;
                        if (WDist.TryParse(parts[3 * i], out rx) && WDist.TryParse(parts[3 * i + 1], out ry) && WDist.TryParse(parts[3 * i + 2], out rz))
                        {
                            vecs[i] = new WVec(rx, ry, rz);
                        }
                    }

                    return(vecs);
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(WPos))
            {
                if (value != null)
                {
                    var parts = value.Split(',');
                    if (parts.Length == 3)
                    {
                        WDist rx, ry, rz;
                        if (WDist.TryParse(parts[0], out rx) && WDist.TryParse(parts[1], out ry) && WDist.TryParse(parts[2], out rz))
                        {
                            return(new WPos(rx, ry, rz));
                        }
                    }
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(WAngle))
            {
                int res;
                if (Exts.TryParseIntegerInvariant(value, out res))
                {
                    return(new WAngle(res));
                }
                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(WRot))
            {
                if (value != null)
                {
                    var parts = value.Split(',');
                    if (parts.Length == 3)
                    {
                        int rr, rp, ry;
                        if (Exts.TryParseIntegerInvariant(parts[0], out rr) && Exts.TryParseIntegerInvariant(parts[1], out rp) && Exts.TryParseIntegerInvariant(parts[2], out ry))
                        {
                            return(new WRot(new WAngle(rr), new WAngle(rp), new WAngle(ry)));
                        }
                    }
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(CPos))
            {
                if (value != null)
                {
                    var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    return(new CPos(Exts.ParseIntegerInvariant(parts[0]), Exts.ParseIntegerInvariant(parts[1])));
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(CVec))
            {
                if (value != null)
                {
                    var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    return(new CVec(Exts.ParseIntegerInvariant(parts[0]), Exts.ParseIntegerInvariant(parts[1])));
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(CVec[]))
            {
                if (value != null)
                {
                    var parts = value.Split(',');

                    if (parts.Length % 2 != 0)
                    {
                        return(InvalidValueAction(value, fieldType, fieldName));
                    }

                    var vecs = new CVec[parts.Length / 2];
                    for (var i = 0; i < vecs.Length; i++)
                    {
                        int rx, ry;
                        if (int.TryParse(parts[2 * i], out rx) && int.TryParse(parts[2 * i + 1], out ry))
                        {
                            vecs[i] = new CVec(rx, ry);
                        }
                    }

                    return(vecs);
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(BooleanExpression))
            {
                if (value != null)
                {
                    try
                    {
                        return(new BooleanExpression(value));
                    }
                    catch (InvalidDataException e)
                    {
                        throw new YamlException(e.Message);
                    }
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(IntegerExpression))
            {
                if (value != null)
                {
                    try
                    {
                        return(new IntegerExpression(value));
                    }
                    catch (InvalidDataException e)
                    {
                        throw new YamlException(e.Message);
                    }
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType.IsEnum)
            {
                try
                {
                    return(Enum.Parse(fieldType, value, true));
                }
                catch (ArgumentException)
                {
                    return(InvalidValueAction(value, fieldType, fieldName));
                }
            }
            else if (fieldType == typeof(ImageFormat))
            {
                if (value != null)
                {
                    switch (value.ToLowerInvariant())
                    {
                    case "bmp":
                        return(ImageFormat.Bmp);

                    case "gif":
                        return(ImageFormat.Gif);

                    case "jpg":
                    case "jpeg":
                        return(ImageFormat.Jpeg);

                    case "tif":
                    case "tiff":
                        return(ImageFormat.Tiff);

                    default:
                        return(ImageFormat.Png);
                    }
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(bool))
            {
                return(ParseYesNo(value, fieldType, fieldName));
            }
            else if (fieldType.IsArray && fieldType.GetArrayRank() == 1)
            {
                if (value == null)
                {
                    return(Array.CreateInstance(fieldType.GetElementType(), 0));
                }

                var options = field != null && field.HasAttribute <AllowEmptyEntriesAttribute>() ?
                              StringSplitOptions.None : StringSplitOptions.RemoveEmptyEntries;
                var parts = value.Split(new char[] { ',' }, options);

                var ret = Array.CreateInstance(fieldType.GetElementType(), parts.Length);
                for (var i = 0; i < parts.Length; i++)
                {
                    ret.SetValue(GetValue(fieldName, fieldType.GetElementType(), parts[i].Trim(), field), i);
                }
                return(ret);
            }
            else if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(HashSet <>))
            {
                var set = Activator.CreateInstance(fieldType);
                if (value == null)
                {
                    return(set);
                }

                var parts     = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                var addMethod = fieldType.GetMethod("Add", fieldType.GetGenericArguments());
                for (var i = 0; i < parts.Length; i++)
                {
                    addMethod.Invoke(set, new[] { GetValue(fieldName, fieldType.GetGenericArguments()[0], parts[i].Trim(), field) });
                }
                return(set);
            }
            else if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(Dictionary <,>))
            {
                var dict      = Activator.CreateInstance(fieldType);
                var arguments = fieldType.GetGenericArguments();
                var addMethod = fieldType.GetMethod("Add", arguments);

                foreach (var node in yaml.Nodes)
                {
                    var key = GetValue(fieldName, arguments[0], node.Key, field);
                    var val = GetValue(fieldName, arguments[1], node.Value, field);
                    addMethod.Invoke(dict, new[] { key, val });
                }

                return(dict);
            }
            else if (fieldType == typeof(Size))
            {
                if (value != null)
                {
                    var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    return(new Size(Exts.ParseIntegerInvariant(parts[0]), Exts.ParseIntegerInvariant(parts[1])));
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(int2))
            {
                if (value != null)
                {
                    var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    return(new int2(Exts.ParseIntegerInvariant(parts[0]), Exts.ParseIntegerInvariant(parts[1])));
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(float2))
            {
                if (value != null)
                {
                    var   parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    float xx    = 0;
                    float yy    = 0;
                    float res;
                    if (float.TryParse(parts[0].Replace("%", ""), NumberStyles.Float, NumberFormatInfo.InvariantInfo, out res))
                    {
                        xx = res * (parts[0].Contains('%') ? 0.01f : 1f);
                    }
                    if (float.TryParse(parts[1].Replace("%", ""), NumberStyles.Float, NumberFormatInfo.InvariantInfo, out res))
                    {
                        yy = res * (parts[1].Contains('%') ? 0.01f : 1f);
                    }
                    return(new float2(xx, yy));
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(float3))
            {
                if (value != null)
                {
                    var   parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    float x     = 0;
                    float y     = 0;
                    float z     = 0;
                    float.TryParse(parts[0], NumberStyles.Float, NumberFormatInfo.InvariantInfo, out x);
                    float.TryParse(parts[1], NumberStyles.Float, NumberFormatInfo.InvariantInfo, out y);

                    // z component is optional for compatibility with older float2 definitions
                    if (parts.Length > 2)
                    {
                        float.TryParse(parts[2], NumberStyles.Float, NumberFormatInfo.InvariantInfo, out z);
                    }

                    return(new float3(x, y, z));
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(Rectangle))
            {
                if (value != null)
                {
                    var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    return(new Rectangle(
                               Exts.ParseIntegerInvariant(parts[0]),
                               Exts.ParseIntegerInvariant(parts[1]),
                               Exts.ParseIntegerInvariant(parts[2]),
                               Exts.ParseIntegerInvariant(parts[3])));
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(Bits <>))
            {
                if (value != null)
                {
                    var parts     = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    var argTypes  = new Type[] { typeof(string[]) };
                    var argValues = new object[] { parts };
                    return(fieldType.GetConstructor(argTypes).Invoke(argValues));
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                var innerType  = fieldType.GetGenericArguments().First();
                var innerValue = GetValue("Nullable<T>", innerType, value, field);
                return(fieldType.GetConstructor(new[] { innerType }).Invoke(new[] { innerValue }));
            }
            else if (fieldType == typeof(DateTime))
            {
                DateTime dt;
                if (DateTime.TryParseExact(value, "yyyy-MM-dd HH-mm-ss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out dt))
                {
                    return(dt);
                }
                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else
            {
                var conv = TypeDescriptor.GetConverter(fieldType);
                if (conv.CanConvertFrom(typeof(string)))
                {
                    try
                    {
                        return(conv.ConvertFromInvariantString(value));
                    }
                    catch
                    {
                        return(InvalidValueAction(value, fieldType, fieldName));
                    }
                }
            }

            UnknownFieldAction("[Type] {0}".F(value), fieldType);
            return(null);
        }
예제 #2
0
        public static object GetValue(string fieldName, Type fieldType, MiniYaml yaml, MemberInfo field)
        {
            var value = yaml.Value?.Trim();

            if (fieldType == typeof(int))
            {
                if (Exts.TryParseIntegerInvariant(value, out var res))
                {
                    return(res);
                }
                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(ushort))
            {
                if (ushort.TryParse(value, NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out var res))
                {
                    return(res);
                }
                return(InvalidValueAction(value, fieldType, fieldName));
            }

            if (fieldType == typeof(long))
            {
                if (long.TryParse(value, NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out var res))
                {
                    return(res);
                }
                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(float))
            {
                if (value != null && float.TryParse(value.Replace("%", ""), NumberStyles.Float, NumberFormatInfo.InvariantInfo, out var res))
                {
                    return(res * (value.Contains('%') ? 0.01f : 1f));
                }
                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(decimal))
            {
                if (value != null && decimal.TryParse(value.Replace("%", ""), NumberStyles.Float, NumberFormatInfo.InvariantInfo, out var res))
                {
                    return(res * (value.Contains('%') ? 0.01m : 1m));
                }
                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(string))
            {
                if (field != null && MemberHasTranslateAttribute[field] && value != null)
                {
                    return(Regex.Replace(value, "@[^@]+@", m => Translate(m.Value.Substring(1, m.Value.Length - 2)), RegexOptions.Compiled));
                }
                return(value);
            }
            else if (fieldType == typeof(Color))
            {
                if (value != null && Color.TryParse(value, out var color))
                {
                    return(color);
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(Hotkey))
            {
                if (Hotkey.TryParse(value, out var res))
                {
                    return(res);
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(HotkeyReference))
            {
                return(Game.ModData.Hotkeys[value]);
            }
            else if (fieldType == typeof(WDist))
            {
                if (WDist.TryParse(value, out var res))
                {
                    return(res);
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(WVec))
            {
                if (value != null)
                {
                    var parts = value.Split(',');
                    if (parts.Length == 3)
                    {
                        if (WDist.TryParse(parts[0], out var rx) && WDist.TryParse(parts[1], out var ry) && WDist.TryParse(parts[2], out var rz))
                        {
                            return(new WVec(rx, ry, rz));
                        }
                    }
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(WVec[]))
            {
                if (value != null)
                {
                    var parts = value.Split(',');

                    if (parts.Length % 3 != 0)
                    {
                        return(InvalidValueAction(value, fieldType, fieldName));
                    }

                    var vecs = new WVec[parts.Length / 3];

                    for (var i = 0; i < vecs.Length; ++i)
                    {
                        if (WDist.TryParse(parts[3 * i], out var rx) && WDist.TryParse(parts[3 * i + 1], out var ry) && WDist.TryParse(parts[3 * i + 2], out var rz))
                        {
                            vecs[i] = new WVec(rx, ry, rz);
                        }
                    }

                    return(vecs);
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(WPos))
            {
                if (value != null)
                {
                    var parts = value.Split(',');
                    if (parts.Length == 3)
                    {
                        if (WDist.TryParse(parts[0], out var rx) && WDist.TryParse(parts[1], out var ry) && WDist.TryParse(parts[2], out var rz))
                        {
                            return(new WPos(rx, ry, rz));
                        }
                    }
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(WAngle))
            {
                if (Exts.TryParseIntegerInvariant(value, out var res))
                {
                    return(new WAngle(res));
                }
                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(WRot))
            {
                if (value != null)
                {
                    var parts = value.Split(',');
                    if (parts.Length == 3)
                    {
                        if (Exts.TryParseIntegerInvariant(parts[0], out var rr) && Exts.TryParseIntegerInvariant(parts[1], out var rp) && Exts.TryParseIntegerInvariant(parts[2], out var ry))
                        {
                            return(new WRot(new WAngle(rr), new WAngle(rp), new WAngle(ry)));
                        }
                    }
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(CPos))
            {
                if (value != null)
                {
                    var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    return(new CPos(Exts.ParseIntegerInvariant(parts[0]), Exts.ParseIntegerInvariant(parts[1])));
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(CVec))
            {
                if (value != null)
                {
                    var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    return(new CVec(Exts.ParseIntegerInvariant(parts[0]), Exts.ParseIntegerInvariant(parts[1])));
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(CVec[]))
            {
                if (value != null)
                {
                    var parts = value.Split(',');

                    if (parts.Length % 2 != 0)
                    {
                        return(InvalidValueAction(value, fieldType, fieldName));
                    }

                    var vecs = new CVec[parts.Length / 2];
                    for (var i = 0; i < vecs.Length; i++)
                    {
                        if (int.TryParse(parts[2 * i], out var rx) && int.TryParse(parts[2 * i + 1], out var ry))
                        {
                            vecs[i] = new CVec(rx, ry);
                        }
                    }

                    return(vecs);
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(BooleanExpression))
            {
                if (value != null)
                {
                    try
                    {
                        return(BooleanExpressionCache[value]);
                    }
                    catch (InvalidDataException e)
                    {
                        throw new YamlException(e.Message);
                    }
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(IntegerExpression))
            {
                if (value != null)
                {
                    try
                    {
                        return(IntegerExpressionCache[value]);
                    }
                    catch (InvalidDataException e)
                    {
                        throw new YamlException(e.Message);
                    }
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType.IsEnum)
            {
                try
                {
                    return(Enum.Parse(fieldType, value, true));
                }
                catch (ArgumentException)
                {
                    return(InvalidValueAction(value, fieldType, fieldName));
                }
            }
            else if (fieldType == typeof(bool))
            {
                if (bool.TryParse(value.ToLowerInvariant(), out var result))
                {
                    return(result);
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(int2[]))
            {
                if (value != null)
                {
                    var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    if (parts.Length % 2 != 0)
                    {
                        return(InvalidValueAction(value, fieldType, fieldName));
                    }

                    var ints = new int2[parts.Length / 2];
                    for (var i = 0; i < ints.Length; i++)
                    {
                        ints[i] = new int2(Exts.ParseIntegerInvariant(parts[2 * i]), Exts.ParseIntegerInvariant(parts[2 * i + 1]));
                    }

                    return(ints);
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType.IsArray && fieldType.GetArrayRank() == 1)
            {
                if (value == null)
                {
                    return(Array.CreateInstance(fieldType.GetElementType(), 0));
                }

                var options = field != null && field.HasAttribute <AllowEmptyEntriesAttribute>() ?
                              StringSplitOptions.None : StringSplitOptions.RemoveEmptyEntries;
                var parts = value.Split(new char[] { ',' }, options);

                var ret = Array.CreateInstance(fieldType.GetElementType(), parts.Length);
                for (var i = 0; i < parts.Length; i++)
                {
                    ret.SetValue(GetValue(fieldName, fieldType.GetElementType(), parts[i].Trim(), field), i);
                }
                return(ret);
            }
            else if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(HashSet <>))
            {
                var set = Activator.CreateInstance(fieldType);
                if (value == null)
                {
                    return(set);
                }

                var parts     = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                var addMethod = fieldType.GetMethod("Add", fieldType.GetGenericArguments());
                for (var i = 0; i < parts.Length; i++)
                {
                    addMethod.Invoke(set, new[] { GetValue(fieldName, fieldType.GetGenericArguments()[0], parts[i].Trim(), field) });
                }
                return(set);
            }
            else if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(Dictionary <,>))
            {
                var dict      = Activator.CreateInstance(fieldType);
                var arguments = fieldType.GetGenericArguments();
                var addMethod = fieldType.GetMethod("Add", arguments);

                foreach (var node in yaml.Nodes)
                {
                    var key = GetValue(fieldName, arguments[0], node.Key, field);
                    var val = GetValue(fieldName, arguments[1], node.Value, field);
                    addMethod.Invoke(dict, new[] { key, val });
                }

                return(dict);
            }
            else if (fieldType == typeof(Size))
            {
                if (value != null)
                {
                    var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    return(new Size(Exts.ParseIntegerInvariant(parts[0]), Exts.ParseIntegerInvariant(parts[1])));
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(int2))
            {
                if (value != null)
                {
                    var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    if (parts.Length != 2)
                    {
                        return(InvalidValueAction(value, fieldType, fieldName));
                    }

                    return(new int2(Exts.ParseIntegerInvariant(parts[0]), Exts.ParseIntegerInvariant(parts[1])));
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(float2))
            {
                if (value != null)
                {
                    var   parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    float xx    = 0;
                    float yy    = 0;
                    if (float.TryParse(parts[0].Replace("%", ""), NumberStyles.Float, NumberFormatInfo.InvariantInfo, out var res))
                    {
                        xx = res * (parts[0].Contains('%') ? 0.01f : 1f);
                    }
                    if (float.TryParse(parts[1].Replace("%", ""), NumberStyles.Float, NumberFormatInfo.InvariantInfo, out res))
                    {
                        yy = res * (parts[1].Contains('%') ? 0.01f : 1f);
                    }
                    return(new float2(xx, yy));
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(float3))
            {
                if (value != null)
                {
                    var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    float.TryParse(parts[0], NumberStyles.Float, NumberFormatInfo.InvariantInfo, out var x);
                    float.TryParse(parts[1], NumberStyles.Float, NumberFormatInfo.InvariantInfo, out var y);

                    // z component is optional for compatibility with older float2 definitions
                    float z = 0;
                    if (parts.Length > 2)
                    {
                        float.TryParse(parts[2], NumberStyles.Float, NumberFormatInfo.InvariantInfo, out z);
                    }

                    return(new float3(x, y, z));
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType == typeof(Rectangle))
            {
                if (value != null)
                {
                    var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    return(new Rectangle(
                               Exts.ParseIntegerInvariant(parts[0]),
                               Exts.ParseIntegerInvariant(parts[1]),
                               Exts.ParseIntegerInvariant(parts[2]),
                               Exts.ParseIntegerInvariant(parts[3])));
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(BitSet <>))
            {
                if (value != null)
                {
                    var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    var ctor  = fieldType.GetConstructor(new[] { typeof(string[]) });
                    return(ctor.Invoke(new object[] { parts.Select(p => p.Trim()).ToArray() }));
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                if (string.IsNullOrEmpty(value))
                {
                    return(null);
                }

                var innerType  = fieldType.GetGenericArguments().First();
                var innerValue = GetValue("Nullable<T>", innerType, value, field);
                return(fieldType.GetConstructor(new[] { innerType }).Invoke(new[] { innerValue }));
            }
            else if (fieldType == typeof(DateTime))
            {
                if (DateTime.TryParseExact(value, "yyyy-MM-dd HH-mm-ss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out var dt))
                {
                    return(dt);
                }
                return(InvalidValueAction(value, fieldType, fieldName));
            }
            else
            {
                var conv = TypeDescriptor.GetConverter(fieldType);
                if (conv.CanConvertFrom(typeof(string)))
                {
                    try
                    {
                        return(conv.ConvertFromInvariantString(value));
                    }
                    catch
                    {
                        return(InvalidValueAction(value, fieldType, fieldName));
                    }
                }
            }

            UnknownFieldAction("[Type] {0}".F(value), fieldType);
            return(null);
        }
예제 #3
0
        public static object GetValue(string fieldName, Type fieldType, string value, MemberInfo field)
        {
            if (value != null)
            {
                value = value.Trim();
            }

            if (fieldType == typeof(int))
            {
                int res;
                if (Exts.TryParseIntegerInvariant(value, out res))
                {
                    return(res);
                }
                return(InvalidValueAction(value, fieldType, fieldName));
            }

            else if (fieldType == typeof(ushort))
            {
                ushort res;
                if (ushort.TryParse(value, NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out res))
                {
                    return(res);
                }
                return(InvalidValueAction(value, fieldType, fieldName));
            }

            if (fieldType == typeof(long))
            {
                long res;
                if (long.TryParse(value, NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out res))
                {
                    return(res);
                }
                return(InvalidValueAction(value, fieldType, fieldName));
            }

            else if (fieldType == typeof(float))
            {
                float res;
                if (float.TryParse(value.Replace("%", ""), NumberStyles.Float, NumberFormatInfo.InvariantInfo, out res))
                {
                    return(res * (value.Contains('%') ? 0.01f : 1f));
                }
                return(InvalidValueAction(value, fieldType, fieldName));
            }

            else if (fieldType == typeof(decimal))
            {
                decimal res;
                if (decimal.TryParse(value.Replace("%", ""), NumberStyles.Float, NumberFormatInfo.InvariantInfo, out res))
                {
                    return(res * (value.Contains('%') ? 0.01m : 1m));
                }
                return(InvalidValueAction(value, fieldType, fieldName));
            }

            else if (fieldType == typeof(string))
            {
                if (field != null && field.HasAttribute <TranslateAttribute>())
                {
                    return(Regex.Replace(value, "@[^@]+@", m => Translate(m.Value.Substring(1, m.Value.Length - 2)), RegexOptions.Compiled));
                }
                return(value);
            }

            else if (fieldType == typeof(Color))
            {
                var parts = value.Split(',');
                if (parts.Length == 3)
                {
                    return(Color.FromArgb(
                               Exts.ParseIntegerInvariant(parts[0]).Clamp(0, 255),
                               Exts.ParseIntegerInvariant(parts[1]).Clamp(0, 255),
                               Exts.ParseIntegerInvariant(parts[2]).Clamp(0, 255)));
                }
                if (parts.Length == 4)
                {
                    return(Color.FromArgb(
                               Exts.ParseIntegerInvariant(parts[0]).Clamp(0, 255),
                               Exts.ParseIntegerInvariant(parts[1]).Clamp(0, 255),
                               Exts.ParseIntegerInvariant(parts[2]).Clamp(0, 255),
                               Exts.ParseIntegerInvariant(parts[3]).Clamp(0, 255)));
                }
                return(InvalidValueAction(value, fieldType, fieldName));
            }

            else if (fieldType == typeof(HSLColor))
            {
                var parts = value.Split(',');

                // Allow old ColorRamp format to be parsed as HSLColor
                if (parts.Length == 3 || parts.Length == 4)
                {
                    return(new HSLColor(
                               (byte)Exts.ParseIntegerInvariant(parts[0]).Clamp(0, 255),
                               (byte)Exts.ParseIntegerInvariant(parts[1]).Clamp(0, 255),
                               (byte)Exts.ParseIntegerInvariant(parts[2]).Clamp(0, 255)));
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }

            else if (fieldType == typeof(Hotkey))
            {
                Hotkey res;
                if (Hotkey.TryParse(value, out res))
                {
                    return(res);
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }

            else if (fieldType == typeof(WRange))
            {
                WRange res;
                if (WRange.TryParse(value, out res))
                {
                    return(res);
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }

            else if (fieldType == typeof(WVec))
            {
                var parts = value.Split(',');
                if (parts.Length == 3)
                {
                    WRange rx, ry, rz;
                    if (WRange.TryParse(parts[0], out rx) && WRange.TryParse(parts[1], out ry) && WRange.TryParse(parts[2], out rz))
                    {
                        return(new WVec(rx, ry, rz));
                    }
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }

            else if (fieldType == typeof(WPos))
            {
                var parts = value.Split(',');
                if (parts.Length == 3)
                {
                    WRange rx, ry, rz;
                    if (WRange.TryParse(parts[0], out rx) && WRange.TryParse(parts[1], out ry) && WRange.TryParse(parts[2], out rz))
                    {
                        return(new WPos(rx, ry, rz));
                    }
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }

            else if (fieldType == typeof(WAngle))
            {
                int res;
                if (Exts.TryParseIntegerInvariant(value, out res))
                {
                    return(new WAngle(res));
                }
                return(InvalidValueAction(value, fieldType, fieldName));
            }

            else if (fieldType == typeof(WRot))
            {
                var parts = value.Split(',');
                if (parts.Length == 3)
                {
                    int rr, rp, ry;
                    if (Exts.TryParseIntegerInvariant(value, out rr) &&
                        Exts.TryParseIntegerInvariant(value, out rp) &&
                        Exts.TryParseIntegerInvariant(value, out ry))
                    {
                        return(new WRot(new WAngle(rr), new WAngle(rp), new WAngle(ry)));
                    }
                }

                return(InvalidValueAction(value, fieldType, fieldName));
            }

            else if (fieldType == typeof(CPos))
            {
                var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                return(new CPos(
                           Exts.ParseIntegerInvariant(parts[0]),
                           Exts.ParseIntegerInvariant(parts[1])));
            }

            else if (fieldType == typeof(CVec))
            {
                var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                return(new CVec(
                           Exts.ParseIntegerInvariant(parts[0]),
                           Exts.ParseIntegerInvariant(parts[1])));
            }

            else if (fieldType.IsEnum)
            {
                try
                {
                    return(Enum.Parse(fieldType, value, true));
                }
                catch (ArgumentException)
                {
                    return(InvalidValueAction(value, fieldType, fieldName));
                }
            }

            else if (fieldType == typeof(bool))
            {
                return(ParseYesNo(value, fieldType, fieldName));
            }

            else if (fieldType.IsArray)
            {
                if (value == null)
                {
                    return(Array.CreateInstance(fieldType.GetElementType(), 0));
                }

                var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

                var ret = Array.CreateInstance(fieldType.GetElementType(), parts.Length);
                for (int i = 0; i < parts.Length; i++)
                {
                    ret.SetValue(GetValue(fieldName, fieldType.GetElementType(), parts[i].Trim(), field), i);
                }
                return(ret);
            }

            else if (fieldType == typeof(Size))
            {
                var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                return(new Size(
                           Exts.ParseIntegerInvariant(parts[0]),
                           Exts.ParseIntegerInvariant(parts[1])));
            }

            else if (fieldType == typeof(int2))
            {
                var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                return(new int2(
                           Exts.ParseIntegerInvariant(parts[0]),
                           Exts.ParseIntegerInvariant(parts[1])));
            }

            else if (fieldType == typeof(float2))
            {
                var   parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                float xx    = 0;
                float yy    = 0;
                float res;
                if (float.TryParse(parts[0].Replace("%", ""), NumberStyles.Float, NumberFormatInfo.InvariantInfo, out res))
                {
                    xx = res * (parts[0].Contains('%') ? 0.01f : 1f);
                }
                if (float.TryParse(parts[1].Replace("%", ""), NumberStyles.Float, NumberFormatInfo.InvariantInfo, out res))
                {
                    yy = res * (parts[1].Contains('%') ? 0.01f : 1f);
                }
                return(new float2(xx, yy));
            }

            else if (fieldType == typeof(Rectangle))
            {
                var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                return(new Rectangle(
                           Exts.ParseIntegerInvariant(parts[0]),
                           Exts.ParseIntegerInvariant(parts[1]),
                           Exts.ParseIntegerInvariant(parts[2]),
                           Exts.ParseIntegerInvariant(parts[3])));
            }

            else if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(Bits <>))
            {
                var parts     = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                var argTypes  = new Type[] { typeof(string[]) };
                var argValues = new object[] { parts };
                return(fieldType.GetConstructor(argTypes).Invoke(argValues));
            }

            else if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                var innerType  = fieldType.GetGenericArguments().First();
                var innerValue = GetValue("Nullable<T>", innerType, value, field);
                return(fieldType.GetConstructor(new[] { innerType }).Invoke(new[] { innerValue }));
            }

            else if (fieldType == typeof(DateTime))
            {
                DateTime dt;
                if (DateTime.TryParseExact(value, "yyyy-MM-dd HH-mm-ss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out dt))
                {
                    return(dt);
                }
                return(InvalidValueAction(value, fieldType, fieldName));
            }

            UnknownFieldAction("[Type] {0}".F(value), fieldType);
            return(null);
        }