如何获得 WCF 代理来构建子集合?
我今天正在学习,我做了我的第一个非常简单的 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 创建一个新的联系人实例(请注意,Contact ctor 使用预先加载来初始化电话 _contactPhones 集合)
最后,我围绕 ContactRepositoryMock.GetContacts 方法创建了一个 WCF 服务包装器,如下所示...
[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 类添加了 Web 引用,并且 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 行
下方有一条波浪线,并返回错误“无法创建 MainPageViewModel 的实例”。
我什至知道该错误的原因。如果我禁用 MainPageViewModel ctor 中的 contact.ContactPhones.Add ... 行,则错误就会消失。
最后,我什至知道为什么错误消失了。这是因为创建 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... 行,错误就会消失。该项目编译并运行。
SO...所有这些只是简单地问...我如何让 Visual Studio 生成将初始化我的集合的代理类。或者我这样做的方式有缺陷吗?我错过了什么?
对于所有详细信息,我深表歉意,但我不确定调用链中的哪个位置可能会出现故障。在这个问题得到解答后,我还将利用所有这些细节来提出更多问题。
赛斯
I am studying today and I did my very first very simple WCF Service. I created a couple of very simple classes as follows (this is simplified a bit) ...
//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; }
}
I have a mock repository class that returns a collection of the contact class
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;
}
}
The Save and Create methods are not shown but Save adds to the _contactList collection and Create creates a new instance of contact (notice that the Contact ctor is using eager loading to init the phone _contactPhones collection)
Finally I created a WCF Service wrapper around the ContactRepositoryMock.GetContacts method as follows...
[ServiceContract(Namespace = "")]
[SilverlightFaultBehavior]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class ContactsService
{
private ContactRepositoryMock _contactRepository = new ContactRepositoryMock();
[OperationContract]
public ObservableCollection<Contact> GetContacts()
{
return _contactRepository.GetContacts();
}
}
The other project is a Silverlight project (which is really what I am s'posed to be studying today.)
In that project I added a Web Reference to my WCF Class and Visual Studio added the proxy class as usual.
I have added a MainPageViewModel in the project as follows:
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");
}
}
}
}
AND the following 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>
That is a lot of background to get to the error and ultimately what is probably a simple explanation.
The XAML line <viewModels:MainPageViewModel x:Key="ViewModels" />
has a squiggly under it and is returning the error "Cannot create and instance of MainPageViewModel".
I even know the CAUSE of that error. If I disable the contact.ContactPhones.Add ... lines that are in the MainPageViewModel ctor then the error goes away.
Finally, I even know why the error goes away. It is because the Reference file that creates the WCF Proxy class is not initializing the ContactPhones collection.
In other words, in the generated class Reference.cs in the proxy if I change the line that reads...
private System.Collections.ObjectModel.ObservableCollection<MVVMDemo.WSProxy.Phone> ContactPhonesField;
to
private System.Collections.ObjectModel.ObservableCollection<MVVMDemo.WSProxy.Phone> ContactPhonesField = new ObservableCollection<Phone>();
then I can re-enable the contact.ContactPhones.Add... lines and the error goes away. The project compiles and runs.
SO...all that to simply ask...how do I get Visual Studio to generate a proxy class that will init my collection. Or is there a flaw in the way I am doing this? What am I missing?
Sorry for all the detail but I was not sure where in the call chain there might be a failure. I am also going to use all of this detail to ask a few more questions after this one gets answered.
Seth
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
WCF 根本不调用任何构造函数。两种选择:
,第二个更容易:
WCF doesn't call any constructors (at all). Two choices:
IMO the second is easier:
在 MainPageViewModel 的构造函数中添加电话号码之前,请尝试添加此行:
contact.ContactPhones = new ObservableCollection();
Try adding this line before you add the phone numbers in the constructor for MainPageViewModel:
contact.ContactPhones = new ObservableCollection();
我不会花费很多精力来让 WCF 生成子集合。如果您必须重新生成代理服务,您的工作将被毁掉。如果您将 WCF 类视为模型,我会创建模型并将其转换为 ViewModel。这样做的好处是您的 ViewModel 实现可以包含映射代码以将模型显式转换为 ViewModel。每次生成 Reference.cs 时,不必重写或更新 ViewModel 类。
I wouldn't go through a lot of effort to get WCF to generate a child collection. You're work will simply be wiped out if you have to regenerate the proxy service. If you are treating your WCF classes as your Models, I'd create and translate your Models into ViewModels. The benefit here is that your ViewModel implementation can contain the mapping code to explicitly convert the Model to the ViewModel. The ViewModel class won't have to be rewritten or updated every time Reference.cs is generated.