Как получить прокси WCF для создания дочерней коллекции? - PullRequest
2 голосов
/ 21 мая 2011

Я учусь сегодня, и я сделал свой самый первый очень простой сервис WCF.Я создал пару очень простых классов следующим образом (это немного упрощено) ...

//contact class  
public class Contact
{
    public int Id { get; set; }


    private ObservableCollection<Phone> _contactPhones = new ObservableCollection<Phone>();
    public ObservableCollection<Phone> ContactPhones
    {
        get { return _contactPhones; }
        set { _contactPhones = value; }
    }

    public string FirstName { get; set; }

    public string LastName { get; set; }
}
// phone class  
public class Phone
{
    public string PhoneNumber { get; set; }
    public PhoneTypes PhoneType { get; set; }
}

У меня есть класс репозитория-макета, который возвращает коллекцию класса контактов

class ContactRepositoryMock : IContactRepository
{
    private readonly ObservableCollection<Contact> _contactList;

    public ContactRepositoryMock()
    {
        _contactList = new ObservableCollection<Contact>();

        Contact contact = this.Create();
        contact.Id = 1;
        contact.FirstName = "Seth";
        contact.LastName = "Spearman";
        contact.ContactPhones.Add(new Phone(){PhoneNumber = "864-555-1111",PhoneType = PhoneTypes.Mobile});
        contact.ContactPhones.Add(new Phone(){PhoneNumber = "864-555-2222",PhoneType = PhoneTypes.Home});

        this.Save(contact);

    }
    public ObservableCollection<Contact> GetContacts()
    {
        return _contactList;
    }

}

Методы Save и Create не отображаются, но Save добавляет в коллекцию _contactList, а Create создает новый экземпляр контакта (обратите внимание, что ctor Contact использует готовую загрузку для инициализации коллекции _contactPhones телефона)

Наконец, ясоздала оболочку службы WCF для метода ContactRepositoryMock.GetContacts следующим образом ...

[ServiceContract(Namespace = "")]
[SilverlightFaultBehavior]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class ContactsService
{
    private ContactRepositoryMock _contactRepository = new ContactRepositoryMock();

    [OperationContract]
    public ObservableCollection<Contact> GetContacts()
    {
        return _contactRepository.GetContacts();
    }
}

Другой проект - это проект Silverlight (который я и собираюсь изучать сегодня).

В этом проекте я добавил веб-ссылку на свой класс WCF, а Visual Studio добавил прокси-класс, как обычно.

Я добавил MainPageViewModel в проект следующим образом:

public class MainPageViewModel : ViewModelBase
{
    public MainPageViewModel()
    {
        if (!IsDesignTime)
        {
            //GetContacts();   //not shown               
        }
        else
        {
            var contactList = new ObservableCollection<Contact>();

            var contact = new Contact {Id = 1, FirstName = "Seth", LastName = "Spearman"};
            contact.ContactPhones.Add(new Phone() { PhoneNumber = "864-555-1111", PhoneType = PhoneTypes.Mobile });
            contact.ContactPhones.Add(new Phone() { PhoneNumber = "864-555-2222", PhoneType = PhoneTypes.Home }); 
            contactList.Add(contact);

            Contacts= contactList;
        }
    }

    private ObservableCollection<Contact> _contacts;
    public ObservableCollection<Contact> Contacts
    {
        get { return _contacts; }
        set
        {
            if (value!=_contacts)
            {
                _contacts = value;
                OnPropertyChanged("Contacts");
            }
        }
    }
}

И следующий XAML

<UserControl x:Class="MVVMDemo.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    xmlns:viewModels="clr-namespace:MVVMDemo.ViewModels"
    d:DesignHeight="300" d:DesignWidth="400">
    <UserControl.Resources>
        <viewModels:MainPageViewModel x:Key="ViewModels" />
    </UserControl.Resources>

    <Grid x:Name="LayoutRoot" 
          DataContext="{Binding Source={StaticResource ViewModels}}"
          Background="White">
    </Grid>
</UserControl>

Это большой фон, чтобы добраться до ошибки и, в конечном итоге, что, вероятно,простое объяснение.

Строка XAML <viewModels:MainPageViewModel x:Key="ViewModels" /> имеет волнистую структуру и возвращает ошибку «Невозможно создать и экземпляр MainPageViewModel».

Я даже знаю ПРИЧИНУ этой ошибки.Если я отключу строки contact.ContactPhones.Add ..., которые находятся в ctor MainPageViewModel, то ошибка исчезнет.

Наконец, я даже знаю, почему ошибка исчезает.Это потому, что файл Reference, который создает прокси-класс WCF, не инициализирует коллекцию ContactPhones.

Другими словами, в сгенерированном классе Reference.cs в прокси, если я изменю строку, которая читает ...

private System.Collections.ObjectModel.ObservableCollection<MVVMDemo.WSProxy.Phone> ContactPhonesField;

до

private System.Collections.ObjectModel.ObservableCollection<MVVMDemo.WSProxy.Phone> ContactPhonesField = new ObservableCollection<Phone>();

, затем я могу снова включить строки contact.ContactPhones.Add ... и ошибка исчезнет.Проект компилируется и запускается.

ТАК ... все это просто спросить ... как мне заставить Visual Studio сгенерировать прокси-класс, который будет инициировать мою коллекцию.Или в том, как я это делаю, есть недостаток?Чего мне не хватает?

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

Сет

Ответы [ 3 ]

4 голосов
/ 21 мая 2011

WCF не вызывает никаких конструкторов (вообще). Два варианта:

  • добавить обратный вызов десериализации ( MSDN )
  • обращаться с этим в собственности

ИМО второй проще:

ObservableCollection<Phone> _contactPhones;
[DataMember]
public ObservableCollection<Phone> ContactPhones
{
    get { return _contactPhones ?? (
        contactPhones = new ObservableCollection<Phone>());
}
0 голосов
/ 23 мая 2011

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

0 голосов
/ 21 мая 2011

Попробуйте добавить эту строку перед добавлением телефонных номеров в конструкторе для MainPageViewModel:

contact.ContactPhones = new ObservableCollection ();

...