WCF对没有“设置”的属性造成窒息。任何解决方法?


97

由于服务方法,我要传递一些类,并且该类具有仅获取属性:

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

服务端出现异常:

System.Runtime.Serialization.InvalidDataContractException:类型'MyNamespace.ErrorBase'中没有为属性'Message'设置的方法。

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

Answers:


106

Give Message是一个公共的getter但受保护的setter,所以只有子类(和DataContractSerializer,因为它欺骗了:)才可以修改该值。


那是一个很好的解决方案!
罗素

谢谢,很高兴它有用!实际上,这只是该技巧的几种用途之一。由于getter和setter在技术上是功能,因此您也可以使用相同的技术来提供原始类型的自定义序列化(也许是XML中的自定义时间格式),而无需使用令人生畏的IDataContractSurrogate。
rh。

28
您甚至可以将其设为私有。串行器不在乎它是私有的,公共的,受保护的,内部的还是受保护的内部。
亚伯

8
并设定throw new NotSupportedException()
传球手

2
private set;如果您使用[DataContract]和,则有作品[DataMember]。如果省略它们,则需要public set;
user276648 '17

12

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

这样的SO是您所追求的: WCF DataContracts


1
因此,我要克服此问题的唯一方法是使它成为方法而不是属性?再次,我不允许对此属性进行“设置”
Andrey

您可以使它成为一个方法(例如,GetMessage(){return“”;}),或者,我很确定您可以告诉WCF序列化器忽略它。我会看到我能找到的并让您知道
罗素

1
这个stackoverflow问题触动了头脑:stackoverflow.com/questions/172681/wcf-datacontracts
Russell 2010年

11
[DataMember(Name = "PropertyName")]
public string PropertyName
{
    get
    {
        return "";
    }
    private set
    { }
}

5

如果您只有一个吸气剂,为什么根本需要序列化该属性。似乎您可以删除只读属性的DataMember属性,而序列化程序将仅忽略该属性。


3
将派生的属性(例如,从ID属性计算出的URL属性)序列化为持久性存储(例如,数据库)确实没有意义-为此表示支持-但将其序列化为API请求返回的表示形式(例如JSON或XML)。
弗洛里安(Florian)

3

您难道没有一个“什么都不做”的二传手吗?

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

还是DataContract序列化器也否?


14
这并不令人讨厌,我只是不想让使用客户端API的开发人员认为他们可以向该属性分配内容。
安德烈,

2

具有DataMember属性的属性始终需要设置。由于应始终为DataContract成员分配值,因此应在客户端应用程序上重新编写simmilar对象。


2

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


2

如果这是一个可行的选择,则不要ErrorBase像下面这样将其定义为基类:

    public interface IError
    {
        string Message
        {
            [OperationContract]
            get;

            // leave unattributed
            set;
        }
    }

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


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.