Trying to map two different types to one value

依然范特西╮ 提交于 2019-12-24 07:36:08

问题


I have a DataMember that I need to be filled in by an api json string...

[DataContract]
public class Values
{
    [DataMember]
    public object value { get; set; }
}

API json string:

[
    {
        "type": "text",
        "values": [
            {
                "value": "Text that is in textfield"
            }
        ]
    },
    {
        "type": "category",
        "values": [
            {
                "value": {
                    "text": "Category title",
                    "color": "#000000"
                }
            }
        ]
    }
]

I map this string to a strong typed object Field like so:

    private List<Field> PrepFieldObject(string response)
    {
        using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(response)))
        {
            DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(List<Field>));
            return (List<Field>)serializer.ReadObject(stream);
        }
    }

but when it gets to mapping Values.value, it throws a hissy fit... I tried solving it like this:

[DataContract]
public class Values
{
    [DataMember]
    public object value
    {
        get {
            return xamlValue;
        }
        set
        {                     
            xamlValue = new Value();

            if( value is string )
            {
                 xamlValue.text = (string)value; // This works fine
            }
            else
            {

                Value theValue = value as Value;
                try
                {
                    xamlValue.text = theValue.text; // Can't get hold of .text even though it does exist in the json.
                    xamlValue.color = theValue.color;
                }
                catch (Exception e)
                {
                }
            }
        }
    }
    public Value xamlValue { get; set; }
}

[DataContract]
public class Value
{
    [DataMember]
    public string text { get; set; }
    [DataMember]
    public string color { get; set; }
}

But it doesn't let me access properties of the object (I guess because they were never mapped by the DataContract)

I've tried adding

[KnownType(typeof(Value))]
[KnownType(typeof(string))]

but that doesn't help either :'(


回答1:


You have to cast it to whatever type the text property belongs to.

((SomeType)value).text



回答2:


You can just use the operator is, but you have to use it for each value that value can assume:

if (value is String)
{
    //do something
}
else if (value is ...)
...

You can read more about is here.




回答3:


You COULD use a dynamic type:

DataContract]
public class Values
{
    [DataMember]
    public dynamic value { get; set; }
}

More about Dynamics




回答4:


If you want a string or the defined string representation of the object use:

String valueAsString = value.ToString()

That is assuming that the other types (besides string) override the ToString() method to provide a meaningful string representation of the object.

Otherwise you would need to use:

KnownValueType kvt = value as KnownValueType
if(kvt!=null)
{
  //access known type properties here
}



回答5:


You will have to use type-casting. Example string:

string abc = (string)value.text;

OR (preferably)

ComplexType comp = value as ComplexType;

UPDATE:

When you are trying to serialize a JSON object and convert it to a strongly-typed object (something my ComplexType is an example of), its important to have the same names for the properties as is in the JSON. After serialization, you should be able to access the property values.

Hope this helps!!!




回答6:


I think you can use reflection to to access your object's property value. Try changing your setter's else part as

else
    {

        Value theValue = value as Value;
        try
        {   
            // pass the object and the property name you're trying to get hold of
            xamlValue.text = PropertyHasValue(theValue, "text"); // Can't get hold of .text even though it does exist in the json. 
            xamlValue.color = PropertyHasValue(theValue, "color");
        }
        catch (Exception e)
        {
        }
    }

And the reflection method

// using reflection to get the object's property value
public static String PropertyHasValue(object obj, string propertyName)
{
    try
    {
        if (obj != null)
        {
            PropertyInfo prop = obj.GetType().GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public);
            if (prop != null)
            {
                string sVal = String.Empty;
                object val = prop.GetValue(obj, null);

                if (prop.PropertyType != typeof(System.DateTime?))
                    sVal = Convert.ToString(val);
                else // format the date to contain only the date portion of it
                    sVal = Convert.ToDateTime(val).Date.ToString("d"); ;

                if (sVal != null)
                {
                    return sVal;
                 }
             }
        }

        return null;
    }
    catch
    {
        return null;
    }
}


来源:https://stackoverflow.com/questions/24171480/trying-to-map-two-different-types-to-one-value

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!