【问题标题】:Trying to map two different types to one value试图将两种不同的类型映射到一个值
【发布时间】:2014-06-11 19:55:40
【问题描述】:

我有一个DataMember,需要用 api json 字符串填写...

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

API json 字符串

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

我将此字符串映射到强类型对象Field,如下所示:

    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);
        }
    }

但是当它映射到Values.value 时,它会发出嘶嘶声……我试着这样解决它:

[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; }
}

但它不允许我访问对象的属性(我猜是因为它们从未被 DataContract 映射)

我试过添加

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

但这也无济于事:'(

【问题讨论】:

  • 您应该避免将自己置于您不知道对象是字符串还是具有您需要获取的某些字符串属性的复杂对象的情况。解决方案将取决于未显示的上下文,但也许您应该先将字符串值从复杂对象中提取出来,然后再将其存储到您的 value 属性中。
  • 在这种情况下,您认为您可以帮我使用 getter 和 setter 吗?如果设置的值不是字符串类型,那么使用对象来代替?如果你找不到时间,我会努力的。不过谢谢。
  • 您不应该首先尝试设置复杂类型。无论您调用此设置器并分配复杂类型的任何代码都应更改为分配该复杂类型的字符串值。在不知道该代码是什么的情况下,我无法说出确切需要更改的内容。
  • 是一个返回json字符串的api。我在 newtonsoft json 旁边使用一个流来映射到强类型类。不幸的是,在这个特定的 [DataMember] 上,它的映射方式不同,所以我需要一种巧妙的方法将它映射到 strong,这取决于它是什么,或者只是作为动态的(但这似乎不适用于 xaml)跨度>
  • 对不起,我是说 DataContractJsonSerializer

标签: c# xaml datamember


【解决方案1】:

您必须将其转换为 text 属性所属的任何类型。

((SomeType)value).text

【讨论】:

    【解决方案2】:

    您可以只使用运算符is,但您必须对value 可以假定的每个值使用它:

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

    你可以阅读更多关于ishere的信息。

    【讨论】:

    • 这假设他在编译时知道所有可能的类型;情况似乎并非如此。
    • 他说它可能是一个字符串或来自 API 的对象。即使它来自 API,至少应该能够知道公共类型。
    • 在运行时,是的,在编译时,不一定。如果其他项目最终要使用他正在编写的代码,他可能正在创建一种类型,该类型将被其他甚至还不存在的类型使用。就此而言,即使这是一个选项,它可能是也可能不是,它仍然是真的不好的做法。 更好的解决方案是避免将自己置于这个位置,正如我上面的评论所提到的,或者至少通过使用接口来利用多态性。跨度>
    【解决方案3】:

    您可以使用动态类型:

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

    More about Dynamics

    【讨论】:

    • 在这种情况下,我假设 xaml 必须具有强类型才能显示某些内容:(
    • 这假设他知道他需要获取对象的什么属性,但他不一定知道,这就是问题所在。
    • 啊,在这种情况下,铸造可能是你唯一的选择
    • 我确实知道...只是因为在父类中有一个名为“type”的属性,我使用我的数据模板选择器打开它来呈现。当它输入“文本”时,该值将是一个字符串。当它是“类别”类型时,值属性需要映射到具有各种其他属性的对象......并且因为我想使用 newtonsoft json 库和流,我发现很难找出我在什么时候可以决定映射为什么
    【解决方案4】:

    如果您想要一个字符串或对象的定义字符串表示,请使用:

    String valueAsString = value.ToString()
    

    这是假设其他类型(除了字符串)覆盖 ToString() 方法以提供对象的有意义的字符串表示。

    否则你需要使用:

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

    【讨论】:

      【解决方案5】:

      您将不得不使用类型转换。示例字符串:

      string abc = (string)value.text;
      

      或(最好)

      ComplexType comp = value as ComplexType;
      

      更新

      当您尝试序列化 JSON 对象并将其转换为强类型对象(我的 ComplexType 就是一个示例)时,具有与 JSON 中相同的属性名称很重要。序列化后,您应该能够访问属性值。

      希望对你有帮助!!!

      【讨论】:

      • 什么是 ComplexType 位?
      • ComplexType 只是您必须创建的类型示例,例如 Person 类或 Student 类。如果您尝试将类型转换为此类类型,则可以使用“as”进行类型安全的类型转换。
      • 不幸的是,您的额外编辑没有帮助。除了需要映射到动态/对象类型之外,序列化工作正常。
      【解决方案6】:

      我认为您可以使用反射来访问对象的属性值。 尝试将您的 setter 的 else 部分更改为

      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)
              {
              }
          }
      

      以及反射方法

      // 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;
          }
      }
      

      【讨论】:

      • 它停止了错误,这是向前迈出的一步(我认为),但它正在努力从对象中获取值(它只是将这些属性设置为 null)。我猜是因为它从未从 json 字符串中序列化?
      • 事实上,PropertyHasValue obj 参数是 null。
      • 如果您传递的对象具有值('文本和颜色'),则此方法应确保返回该值。检查是否有其他问题。
      • DataContractJsonSerializer 似乎适用于除此双重类型属性之外的所有其他内容。是不是 DataContractJsonSerializer 对 "object" 类型不好?尽管它似乎确实可以很好地映射字符串!
      • 我是这么认为的,它可以很好地映射字符串但不确定DataContractJsonSerializer如何处理对象映射。
      猜你喜欢
      • 2021-04-11
      • 2018-02-28
      • 2011-05-30
      • 1970-01-01
      • 1970-01-01
      • 2016-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多