Переопределение ToString с помощью пользовательского типа данных

В основном у меня есть следующий код:

var json = new JValue { Object = new Dictionary<string, JValue>() };
json["name"] = new JValue("Lebron James");
json["age"] = new JValue(23);

if (json.Type == JType.Object)
{
    foreach (var value in json.Object)
    {
        System.Console.WriteLine(value.ToString());
    }
}

Пользовательский класс и тип данных следующие:

public enum JType
{
    Null,
    Bool,
    Number,
    String,
    Array,
    Object,
}

public class JValue
{
    public JType Type { get; private set; }
    private JsonValue Value { get; set; }

    public JValue()
    {
        Type = JType.Null;
    }

    public JValue(bool value)
    {
        Type = JType.Bool;
        Value = new JsonBool { Value = value };
    }

    public JValue(double value)
    {
        Type = JType.Number;
        Value = new JsonNumber { Value = value };
    }

    public JValue(string value)
    {
        Type = JType.String;
        Value = new JsonString { Value = value };
    }

    public JValue(List<JValue> values)
    {
        Type = JType.Array;
        Value = new JsonArray { Values = values };
    }

    public JValue(Dictionary<string, JValue> values)
    {
        Type = JType.Object;
        Value = new JsonObject { Values = values };
    }

    public bool Null
    {
        get { return Type == JType.Null; }
        set { Type = JType.Null; Value = null; }
    }

    public bool Bool
    {
        get
        {
            if (Type != JType.Bool) throw new InvalidCastException();
            return ((JsonBool)Value).Value;
        }
        set
        {
            Type = JType.Bool;
            Value = new JsonBool { Value = value };
        }
    }

    public double Number
    {
        get
        {
            if (Type != JType.Number) throw new InvalidCastException();
            return ((JsonNumber)Value).Value;
        }
        set
        {
            Type = JType.Number;
            Value = new JsonNumber { Value = value };
        }
    }

    public string String
    {
        get
        {
            if (Type != JType.String) throw new InvalidCastException();
            return ((JsonString)Value).Value;
        }
    }

    public List<JValue> Array
    {
        get
        {
            if (Type != JType.Array) throw new InvalidCastException();
            return ((JsonArray)Value).Values;
        }
        set
        {
            Type = JType.Array;
            Value = new JsonArray { Values = value };
        }
    }

    public Dictionary<string, JValue> Object
    {
        get
        {
            if (Type != JType.Object) throw new InvalidCastException();
            return ((JsonObject)Value).Values;
        }
        set
        {
            Type = JType.Object;
            Value = new JsonObject { Values = value };
        }
    }

    public JValue this[string key]
    {
        get { return Object[key]; }
        set { Object[key] = value; }
    }

    public int Count
    {
        get { return Array.Count; }
    }

    public JValue this[int index]
    {
        get { return Array[index]; }
        set { Array[index] = value; }
    }

    public override string ToString()
    {
        return Value.ToString();
    }
}

internal class JsonValue
{
}

internal class JsonBool : JsonValue
{
    public bool Value;
    public override string ToString()
    {
        return Value.ToString();
    }
}

internal class JsonNumber : JsonValue
{
    public double Value;
    public override string ToString()
    {
        return Value.ToString();
    }
}

internal class JsonString : JsonValue
{
    public string Value;
    public override string ToString()
    {
        return Value.ToString();
    }
}

internal class JsonArray : JsonValue
{
    public List<JValue> Values;
}

internal class JsonObject : JsonValue
{
    public Dictionary<string, JValue> Values;
}

Я попытался переопределить ToString() с помощью этой функции, но она не дает мне значения.

public override string ToString()
{
    return Value.ToString();
}

Любой совет будет принят во внимание.


person Tommizzy    schedule 13.10.2016    source источник
comment
Какой результат вы ожидаете увидеть?   -  person Eugene Pawlik    schedule 14.10.2016
comment
Я пытаюсь вывести только само значение.   -  person Tommizzy    schedule 14.10.2016


Ответы (2)


Вы должны переопределить метод ToString() в каждом классе, производном от JsonValue, потому что JValue.ToString() вызывает метод JsonValue.ToString(), который не переопределен, чтобы он отображал полное имя класса.

Кроме того, я предлагаю заменить общедоступные поля на общедоступные автоматические свойства.

Так, например:

internal class JsonBool : JsonValue
{
    public bool Value { get; set; }

    public string override ToString()
    {
        return Value.ToString();
    }
}

ОБНОВЛЕНИЕ №1:

Лучшим решением было бы ввести универсальный тип, чтобы вы могли избежать множества переопределений ToString().

internal class JsonValue<T>
{
    public T Value { get; set; }

    public override string ToString()
    {
        return Value.ToString();
    }
}

internal class JsonBool : JsonValue<bool>
{
}

internal class JsonDouble : JsonValue<double>
{
}
person Gabor    schedule 13.10.2016
comment
Это работает для инициализированной строки, например: var person = new JValue(Lebron); - person Tommizzy; 14.10.2016
comment
Когда я пытаюсь отобразить значения для Dictionary и Arrays, я получаю что-то вроде этого: System.Collections.Generic.Dictionary`2[System.String,oop_hw.JValue]. Я предполагаю, что мне нужно для каждого цикла в классах словаря и массива, но я не уверен, как его построить. - person Tommizzy; 14.10.2016

Ответ Габора правильный, что вам нужно переопределить ToString для производных объектов JsonValue. Другие его советы о дженериках и замене полей свойствами тоже хороши.

Для ваших типов массивов и объектов вам нужно будет перебрать значения, содержащиеся в этих типах. Возможно, вам придется поиграть с кодом, чтобы получить результат, который вы хотите.

Обратите внимание, что приведенный ниже код не учитывает вложенные элементы. Например, если ваш JsonObject содержит JValue, это тоже JsonObject содержит больше значений.

internal class JsonArray : JsonValue
{
    public List<JValue> Values;
    public override string ToString()
    {
        return string.Join(", ", Values ?? Enumerable.Empty<JValue>());
    }
}

internal class JsonObject : JsonValue
{
    public Dictionary<string, JValue> Values;
    public override string ToString()
    {
        if (Values == null || Values.Count <= 0)
        {
            return "";
        }

        var builder = new StringBuilder();
        foreach (var item in Values)
        {
            builder
                .AppendFormat("{0}: {1}", item.Key, item.Value)
                .AppendLine();
        }

        return builder.ToString();
    }
}
person Eugene Pawlik    schedule 14.10.2016