【问题标题】:WCF chokes on properties with no "set ". Any workaround?WCF 在没有“设置”的属性上阻塞。任何解决方法?
【发布时间】:2011-01-20 08:45:21
【问题描述】:

我有一些作为服务方法的结果传递的类,并且该类有一个 get-only 属性:

[DataContract]
public class ErrorBase
{
  [DataMember]
  public virtual string Message { get { return ""; } }
}

我在服务端遇到异常:

System.Runtime.Serialization.InvalidDataContractException:未设置 类型“MyNamespace.ErrorBase”中属性“消息”的方法。

我必须将此属性作为唯一的 getter,我不能允许用户为其分配值。我可以使用任何解决方法吗?还是我缺少一些额外的属性?

【问题讨论】:

    标签: c# wcf properties datacontractserializer


    【解决方案1】:

    给 Message 一个公共的 getter 但受保护的 setter,这样只有子类(和 DataContractSerializer,因为它作弊 :) 可以修改值。

    【讨论】:

    • 谢谢,很高兴它有用!这实际上只是这个技巧的几种用途之一。由于 getter 和 setter 在技术上是函数,因此您也可以使用相同的技术来提供原始类型的自定义序列化(可能是 XML 中的自定义时间格式),而无需使用令人生畏的 IDataContractSurrogate。
    • 您甚至可以将其设为私有。序列化器不介意它是私有的、公共的、受保护的、内部的还是受保护的内部的。
    • 并制作 setter throw new NotSupportedException()
    • 不要忘记 [DataMember] 属性 :)
    • 如果您使用[DataContract][DataMember],则拥有private set; 有效。如果省略它们,则需要public set;
    【解决方案2】:

    即使您不需要更新值,WCFSerializer 也会使用 setter 来反序列化对象(并重新设置值)。

    这就是你所追求的: WCF DataContracts

    【讨论】:

    • 所以我克服这个问题的唯一方法是让它成为方法而不是属性?同样,我不能允许在此属性上“设置”
    • 您可以将其设为方法(例如 GetMessage() { return ""; }),或者我很确定您可以告诉 WCF 序列化程序忽略它。我会看看我能找到什么并告诉你。,
    • 这个 stackoverflow 问题一针见血:stackoverflow.com/questions/172681/wcf-datacontracts
    【解决方案3】:
    [DataMember(Name = "PropertyName")]
    public string PropertyName
    {
        get
        {
            return "";
        }
        private set
        { }
    }
    

    【讨论】:

      【解决方案4】:

      难道你不能只有一个“无所事事”的二传手吗?

      [DataContract]
      public class ErrorBase
      {
        [DataMember]
        public virtual string Message 
        {
            get { return ""; } 
            set { }
        }
      }
      

      或者 DataContract 序列化程序是否也有问题?

      【讨论】:

      • 没有错,我只是不想让使用客户端 API 的开发人员认为他们可以为属性分配东西。
      【解决方案5】:

      如果你只有一个 getter,为什么你需要序列化属性。似乎您可以删除只读属性的 DataMember 属性,而序列化程序只会忽略该属性。

      【讨论】:

      • 将派生属性(例如,从 ID 属性计算的 URL 属性)序列化到持久存储(例如,数据库)确实没有意义 - 对此表示赞成 - 但它将其序列化为 API 请求返回的表示(例如 JSON 或 XML)确实有意义。
      【解决方案6】:

      具有 DataMember 属性的属性始终需要设置。您应该在客户端应用程序上重新编写类似的对象,因为始终可以为 DataContract 成员分配值。

      【讨论】:

        【解决方案7】:

        我在使用 ASP.NET MVC 时遇到了这个问题,我想使用 DataContractSerializer 以便能够控制 JSON 输出中项目的名称。最终我将序列化程序切换到 JSON.NET,它通过 [JsonProperty(PropertyName = "myName")] 支持没有设置器的属性(DataContractSerializer 不支持)和属性名称控制(ASP.NET MVC 中的内置 JSON 序列化程序不支持)。

        【讨论】:

          【解决方案8】:

          如果这是一个可行的选择,那么不要将ErrorBase 作为基类,而是将其定义如下:

              public interface IError
              {
                  string Message
                  {
                      [OperationContract]
                      get;
          
                      // leave unattributed
                      set;
                  }
              }
          

          现在,即使存在 setter,客户端也无法通过 WCF 通道访问它,因此它就像是私有的。

          【讨论】:

            【解决方案9】:

            如果您的序列化程序是DataContractJsonSerializer(或任何DataContractSerializer)类型,您还可以在构造函数中使用DataContractSerializerSettings,并将SerializeReadOnlyTypes 属性设置为true。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2016-01-18
              • 2010-10-20
              • 1970-01-01
              • 1970-01-01
              • 2011-01-18
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多