WCF DataContract со свойствами только для чтения - PullRequest
15 голосов
/ 22 марта 2010

Я пытаюсь вернуть сложный тип из метода службы в WCF. Я использую C # и .NET 4. Этот сложный тип должен быть инвариантным (так же, как строки .net). Кроме того, служба только возвращает его и никогда не получает в качестве аргумента.

Если я пытаюсь определить только геттеры по свойствам, я получаю ошибку во время выполнения. Я думаю, это потому, что никакие сеттеры не вызывают сериализацию. Тем не менее, я думаю, этот тип должен быть инвариантным.

Пример:

[DataContract]
class A 
{
   [DataMember]
   int ReadOnlyProperty {get; private set;}
}

Служба не загружается из-за проблемы с сериализацией.

Есть ли способ сделать свойства только для чтения в WCF DataContract? Возможно, заменив сериализатор? Если так, то как? Если нет, что бы вы предложили для этой проблемы?

Спасибо
Асаф

Ответы [ 8 ]

14 голосов
/ 22 марта 2010

поставить [DataMember] на поле поддержки, вам не понадобится сеттер.

9 голосов
/ 28 января 2014

Сделайте ваш установщик общедоступным, чтобы удовлетворить сериализатор, но просто ничего не делайте на установщике. Не "пурист", но делает это

public string MyProperty 
{
    get {
        return this._myProperty
    }
    set {}
}
4 голосов
/ 02 октября 2014

Вы не можете сделать свойства доступными только для чтения, однако вы можете приблизиться к свойствам только для чтения, сделав поля частью вашего контракта вместо свойств:

[DataContract]
public class A 
{
   public class A(){}
   public class A(int readonlyproperty){ _readonlyproperty = readonlyproperty}

   [DataMember(Name = "ReadOnlyProperty")]
   internal int _readonlyproperty;

   public int ReadOnlyProperty {
      get {return _readonlyproperty;}
      private set {_readonlyproperty = value;}
}

затем сделайте ваши внутренние доступными в wcf:

[assembly: InternalsVisibleTo("System.Runtime.Serialization")]

Некоторые примеры того, как использовать это в ваших интересах: wcf-and-datacontract-serialization-internals-and-tips

3 голосов
/ 24 марта 2010

Поле DataMember не может быть доступно только для чтения, потому что wcf не сериализует объект как есть и каждый раз, когда начинается десериализация, создает новый экземпляр объекта, используя конструктор по умолчанию Диспетчеры используют установщики для установки значений полей после десериализации.

Но весь верхний текст может быть большой ошибкой:)

Чтобы сделать их действительно доступными только для чтения, настройте логику сервера, проверяя значения этого поля.

0 голосов
/ 30 апреля 2015

WCF должен иметь возможность сериализовать / десериализовать свойство, что невозможно с частной собственностью.Чтобы иметь свойство только для чтения (внутри сложного типа):

  • Декорировать класс как [DataContract (IsReference = true)]
  • Декорировать каждое свойство как [DataMember]
  • Public Get, Внутренний Набор
    [DataContract(IsReference = true)]
    public class Format : ValueObject<Format>
    {
        [DataMember]
        public int Height { get; internal set; }
    }
0 голосов
/ 20 апреля 2015

На самом деле вы можете сделать поля только для чтения сериализуемыми. Вам необходимо установить для свойства 'SerializeReadOnlyTypes' объекта DataContractSerializerSettings значение 'True' при создании DataContractSerializer, как показано ниже:

var xmlSerializer = new DataContractSerializer(typeof(yourTypeHere),  new DataContractSerializerSettings {SerializeReadOnlyTypes=true});

См. Описание и подробности MSDN здесь: https://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractserializersettings(v=vs.110).aspx

0 голосов
/ 25 августа 2014

Как уже говорили другие, WCF нужны геттеры и сеттеры. При этом я пришел сюда с тем же вопросом, и ответы заставили меня спросить, зачем мне нужно свойство только для чтения. Если вы используете шаблон MVVM, классом, возвращаемым службой, является Модель, и поэтому он не должен предоставляться непосредственно UI. Вы можете легко сделать ViewModel только для чтения. В качестве альтернативы вы можете использовать класс фасадов, не предназначенный для пользовательского интерфейса.

0 голосов
/ 22 марта 2010

Вы пытались сделать сеттер приватным?

Что-то вроде:

public string MyProperty
{
get;
private set;
}
...