问题
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