ObservableCollection и CollectionChanged как контракт данных WCF

Я использую DataContract с ObservableCollection:

[DataContract(Namespace = Terms.MyNamespace)]
public class MyContract 
{
internal MyContract ()
        {
            List = new ObservableCollection<string>();
        }
[DataMember]
private ObservableCollection<string> list;

[XmlArray("list")]
        public ObservableCollection<string> List
        {
            get
            {
                return list;
            }
            set
            {
                list = value;
                list.CollectionChanged += (s, e) =>
                    { 
                        Console.WriteLine("It is never happens!! Why?"); 
                    };
            }
        }
...

Итак, когда я работаю со своей коллекцией вот так.

MyContract contract = new MyContract();
contract.List.Add("some");

Элемент был добавлен, но событие CollectionChanged не сработало.

Почему?


person weqew q    schedule 23.12.2011    source источник
comment
Контракт данных WCF не должен содержать какую-либо логику / код, поскольку этот код не может быть сериализован по каналу связи от сервера к клиенту и обратно. WCF - это система передачи сообщений. Все, что передается от клиента к серверу и обратно, является сериализованными сообщениями XML, и они не могут содержать поведение / логику / код.   -  person marc_s    schedule 23.12.2011
comment
Хорошо, возможно ли что-нибудь сделать в этой ситуации? Мне нужно пометить мой контракт (например, установить дополнительно логическое поле datamember в значение true), когда в коллекции клиента была изменена. Неявно установить это поле в коде невозможно ...   -  person weqew q    schedule 23.12.2011
comment
Эти контракты данных на стороне клиента будут частичными классами - вы можете расширить их, чтобы обрабатывать обнаружение изменений и установку свойства внутри контракта данных. Вам нужен этот флаг только на клиенте ?? Или вам нужно в какой-то момент передать это обратно на сервер ??   -  person marc_s    schedule 23.12.2011
comment
Мне нужно передать этот флаг обратно на сервер. И проблема в том, что когда я продляю свой контракт, он не работает для наблюдаемого сбора. Поэтому, если я устанавливаю свой флаг в разделе set свойства - он работает нормально, но если я работаю с наблюдаемыми методами добавления, вставки и удаления коллекции, я не могу обнаружить, что эта коллекция была изменена. Потому что событие OnCollectionChanged не работает.   -  person weqew q    schedule 23.12.2011


Ответы (1)


Это потому, что вы не сериализуете List, пока сериализуете list. Таким образом, во время десериализации он не будет вызывать установщик списка, поэтому не будет подписываться на событие. В вашем случае вы можете просто пометить List DataMemberAttribute вместо list, например:

[DataContract]
public class MyContract
{
    private ObservableCollection<string> list;

    internal MyContract()
    {
        List = new ObservableCollection<string>();
    }

    [DataMember]
    public ObservableCollection<string> List
    {
        get
        {
            return list;
        }
        private set
        {
            list = value;
            list.CollectionChanged += 
               (s, e) => 
                   Console.WriteLine("It is never happens!! Why? - Are you sure?!");
        }
    }
}

Использование:

var obj = new MyContract();

var serializer = new DataContractSerializer(typeof(MyContract));

using (var ms = new MemoryStream())
{
    serializer.WriteObject(ms, obj);

    ms.Seek(0, SeekOrigin.Begin);

    var result = serializer.ReadObject(ms) as MyContract;

    result.List.Add("a");
}

В этом случае событие сработает.

person Kirill Polishchuk    schedule 28.12.2011