2010-03-22 2 views
12

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

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

Пример:

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

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

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

Спасибо,
Асаф

+0

Вы можете быть в состоянии использовать только для чтения поля (* не свойства *) и инициализировать их в конструкции вашего класса. Также ..., возможный дубликат: http://stackoverflow.com/q/1873741/945456 –

+0

Это еще более важно сегодня с переходом к неизменяемым классам и поддержкой C# -6.0 для автоматически реализованных свойств get-only. – binki

ответ

1

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

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

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

-1

Вы пробовали сделать сеттер частный?

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

public string MyProperty 
{ 
get; 
private set; 
} 
+0

Да. Это точно моя проблема. –

+0

Так это исправлено? Или это то, что вы пытались? –

+0

Не работает. Если я сделаю MyProperty [DataMember], я получаю ошибку выполнения, вызванную, насколько я понимаю, из сериализации. Это происходит, как только сервис загружается - даже при работе с клиентом. –

13

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

+0

Но это не будет быть готовым только и не будет выражать, что он должен быть только для чтения. –

+4

он никогда не будет доступен только для чтения. Datacontract при переносе по проводу - это просто XML, вы не можете сделать кусок XML только для чтения. Вы не можете сделать * make * * кто бы ни находился на другом конце провода, чтобы не изменять его значение. Это просто не работает. –

+0

Вы можете просто проигнорировать значение, если оно передано службе? Только для чтения вы имеете в виду, что служба возвращает только это? –

7

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

public string MyProperty 
{ 
    get { 
     return this._myProperty 
    } 
    set {} 
} 
0

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

3

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

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

Следующая сделать ваши внутренние accesable в ФОС:

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

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

0

на самом деле, вы можете сделать только для чтения полей сериализации.Вы должны установить свойство «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

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

  • класс Украсьте как [DataContract (IsReference = ИСТИНА)]
  • Украсьте каждый/свойство, как [DataMember]
  • Public ГЭТ, Внутренняя Набор
[DataContract(IsReference = true)] 
    public class Format : ValueObject<Format> 
    { 
     [DataMember] 
     public int Height { get; internal set; } 
    }