Коллекция интерфейсов и WCF - PullRequest
2 голосов
/ 10 ноября 2010

Я использую C # и WCF для веб-сервисов.У меня есть переменная-член класса, который реализует IEnumerable.Я попытался сериализовать его как часть моего контракта на данные, выполнив:

[DataContract]
class Item
{
    [DataMember]
    private IEnumerable<KeyValuePair<string, object>> Member1
    {
        get { return this._Properties; }
        set { this._Properties = Value; }
    }
}

Где _Properties имеет тип:

class PropertiesCollection:IEnumerable<KeyValuePair<string, object>>
{
    ...
}

Я думал, что WCF будет сериализовать Member1 как IEnumerableпотому что это тип, который я дал этому члену, но я получаю InvalidDataContractExceptiom с этим сообщением:

Тип PropertyCollection не может быть сериализован.Попробуйте пометить его атрибутом DataContractAttribute и пометить все его элементы, которые вы хотите сериализовать, атрибутом DataMemberAttribute.Если тип является коллекцией, попробуйте пометить его с помощью CollectionDataContractAttribute.Информацию о других поддерживаемых типах см. В документации Microsoft .NET Framework.

Кажется, что WCF смотрит на тип времени выполнения объекта, передаваемого через Member1 (PropertyCollection), а не на тип свойства (IEnumenable),Это понимание правильно?Единственное исправление, добавляющее [CollectionDataContract] к PropertiesCollection?Я бы предпочел указывать контракт на обслуживание неконкретным (т. Е. Он просто знает, что iot является IEnumerable), если это возможно.

Ответы [ 4 ]

1 голос
/ 10 декабря 2010

Реальный ответ на этот вопрос заключается в том, что существует ряд требований, которым тип должен соответствовать, чтобы быть действительной коллекцией DataContract:

  1. Он должен иметь конструктор без параметров
  2. Он долженесть метод Add.

Когда я реализовал их, моя проблема ушла.

1 голос
/ 10 ноября 2010

Вне моей головы: я думаю, вам нужно украсить свойство Member1 атрибутом KnownType.

см .: http://msdn.microsoft.com/en-us/library/ms730167.aspx

[DataContract]
[KnownType(typeof(PropertiesCollection))] //<--- this guy here
class Item
{
    [DataMember]
    private IEnumerable<KeyValuePair<string, object>> Member1
    {
        get { return this._Properties; }
        set { this._Properties = Value; }
    }
}

Добавление кода из примера 2 в ссылку выше, чтобы показать, что, хотя атрибут является декоратором класса, он применяется к DataMember:

public interface ICustomerInfo {}

[DataContract(Name = "Customer")]
public class CustomerTypeA : ICustomerInfo {}

[DataContract(Name = "Customer")]
public class CustomerTypeB : ICustomerInfo {}

[DataContract]
[KnownType(typeof(CustomerTypeB))] //<-- check it! This applies to 'buyer'
public class PurchaseOrder
{
    [DataMember]
    ICustomerInfo buyer;

    [DataMember]
    int amount;
}
0 голосов
/ 15 апреля 2014

Самое простое решение:

  1. создать новый сериализуемый класс, содержащий ключ и значение
  2. Передайте этот класс в любой коллекции
0 голосов
/ 10 ноября 2010

Вы должны иметь DataContract перед PropertiesCollection определением класса:

 [DataContract]
 class PropertiesCollection:IEnumerable<KeyValuePair<string, object>>
 {
    ...
 }

Каждый из типов, которые входят в сериализацию, должен быть [DataContract] или [Serializable]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...