WCF通用字典和了解WCF

好的,我在解决特定问题时遇到了很多困难。 通过服务传输对象。 从概念上讲,它是有道理的……我想? 根据我的阅读,除非已明确定义,否则无法序列化Generic。

所以我想提供我的榜样; 我根本无法上class。 意思是; 我确信还有其他人也遇到了一些困难。 当你提供帮助时,如果你能提供代码; 这将起作用并解释它。 这样我就可以完全理解这个问题。 这对我很有帮助,了解Windows Communication Foundation。

目标是一个客户端应用程序,它只有五个字段; 在其中“发布”到服务器。

  • 名字
  • 电子邮件地址
  • 电话号码
  • 网站地址

这不是太复杂。

这就是我所做的,在我学习WCF的过程中,我尽可能地将其包含在基于SOA的应用程序中。 这样它就可以提供代码的可重用性。

型号/数据合同:

#region Using Reference... using System.Runtime.Serialization; using System.Collections.Generic; using System.Threading.Tasks; using System.Text; using System.Linq; using System; #endregion namespace _2Do.Model.Customer { [DataContract(IsReference = true)] public class Person { #region Declared Variable. string first; string last; string email; string phone; string site; #endregion #region Constructor: Person() { // Empty Constructor. } #endregion #region Data Member Properties: [DataMember()] public string First { get { return first; } set { first = value; } } [DataMember()] public string Last { get { return last; } set { last = value; } } [DataMember()] public string Email { get { return email; } set { email = value; } } [DataMember()] public string Phone { get { return phone; } set { phone = value; } } [DataMember()] public string Site { get { return site; } set { site = value; } } #endregion } } 

这就是应该通过元数据为客户端公开的对象; 所以对于Service接口,我尝试了这个:

 #region Using Reference... using System.Collections.Generic; using System.Threading.Tasks; using System.ServiceModel; using _2Do.Model.Customer; using System.Text; using System.Linq; using System; #endregion namespace _2Do.Contract.Customer { [ServiceContract (Namespace = "https://_2Do") ] public interface IPerson { [OperationContract()] Person SetCustomer(Dictionary info); } } 

所以上面是目标; 转移我的Person对象; 存储到字典中。 另一件需要注意的事情; 我认为通过引用传递值的实现将有助于序列化。 我想一旦数据存储在内存中; 它将包含一个明确的方法来处理它。 这是我的错吗?

这就是我的DataContractServiceContract

此时的实现是这样的:

 #region Using Reference... using System.Collections.Generic; using System.Threading.Tasks; using _2Do.Contract.Customer; using System.ServiceModel; using _2Do.Model.Customer; using System.Text; using System.Linq; using System; #endregion namespace _2Do.Service.Customer { [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] public class PersonService : IPerson { #region Constructor: PersonService() { // Empty Constructor. } #endregion #region Implement Interface: Person SetCustomer(Dictionary info) { // Receive an error that indicates; best overload method. // Contains invalid arguments. } #endregion } } 

然后我创建了一个单独的项目来托管应用程序; 我创建了一个空文本文件并将其重命名为PersonService.svc

然后我把它放在:

哪个应该指向正确的命名空间; 在PersonService我有一个web.config文件,其中包含要在Internet Information System中托管的最低配置。 我认为这将允许我绕过定义我的地址,绑定和合同。 因为IIS现在可以为我做这一切。

然后我创建了一个ClientProxy类; 它包含几乎DataContract的镜像。 然后我创建了实际的客户端应用程序:

 PersonProxy p = new PersonProxy(); p.First = txtFirst.Text; p.Last = txtLast.Text; p.Email = txtEmail.Text; p.Phone = txtPhone.Text; p.Site = txtSite.Text; Dictionary i = new Dictionary(); i.Add(Guid.NewGuid(), p); 

我有这些项目:

  • Model – > DataContract
  • 合同 – > ServiceContract
  • 服务 – >接口实现
  • 主机 – >商店服务/ Svc
  • ClientProxy – >接口实现
  • 客户端 – >链接到要inheritance的ClientProxy的实际值。

这是我在客户端上使用它的方式。 我不确定我在哪里搞砸了。 我真的很想了解WCF,因为我需要为工作项目学习它。 但我很沮丧,觉得很愚蠢,因为我似乎无法解决这个问题。

如果我按照教程,它的工作原理。 但是一旦我回到原来的实现,它就失败了。 不知道我哪里或哪里出错了。 一些手握将不胜感激; 但如果你能一步一步地解释它,那就太受欢迎了。 所以我可以从我的错误中吸取教训来实际改进。

我无法让它将变量存储在服务器上,传输,我不知道为什么在这一点上。

我仍然不确定你的代码为什么不起作用。 也许我不理解IIS中的托管以及我应该这样做。 但是,下面是我能提出的最简单的Web服务+客户端的完整工作示例。 希望它能帮助您找到并解决问题。

首先, 项目结构 :一个类库项目中的合同,控制台应用程序中的服务和主机,另一个控制台应用程序中的客户端。

数据合同:

 [DataContract] public class Person { [DataMember] public string Name { get; set; } [DataMember] public string Email { get; set; } } 

服务合约:

 [ServiceContract] public interface IPerson { [OperationContract] Person SetCustomer(Dictionary info); } 

服务:

 public class PersonService : IPerson { public Person SetCustomer(Dictionary info) { foreach (var person in info.Values) { Console.WriteLine("Name: {0} | Email: {1}", person.Name, person.Email); } var p = new Person { Name = "John Doe", Email = "John@Doe.com" }; return p; } } 

服务主机(在主机项目的Program.cs中):

 static void Main(string[] args) { using (ServiceHost host = new ServiceHost(typeof(PersonService), new Uri("http://localhost:8080"))) { host.Open(); Console.WriteLine("Ready!"); Console.ReadKey(true); host.Close(); } } 

最后,客户端(在自己的项目的Program.cs中):

 static void Main(string[] args) { var binding = new BasicHttpBinding(); var endpoint = new EndpointAddress("http://localhost:8080/"); using (var factory = new ChannelFactory(binding, endpoint)) { var request = new Dictionary(); request[Guid.NewGuid()] = new Person { Name = "Bob", Email = "Bob@abc.com" }; var client = factory.CreateChannel(); var result = client.SetCustomer(request); Console.WriteLine("Name: {0} | Email: {1}", result.Name, result.Email); factory.Close(); } Console.ReadKey(true); } 

希望这可以帮助!

您真的需要将词典作为服务合同的参数吗? 保持简单 – 改用List。 我的建议是:

1)将Guid属性添加到Person数据协定中

 [DataContract(IsReference = true)] public class Person { #region Constructor: public Person() { // Empty Constructor. } #endregion #region Data Member Properties: [DataMember] public Guid Guid { get; set; } [DataMember] public string First { get; set; } [DataMember] public string Last { get; set; } [DataMember] public string Email { get; set; } [DataMember] public string Phone { get; set; } [DataMember] public string Site { get; set; } #endregion } 

2)更改服务合同以使用List:

 [ServiceContract (Namespace = "https://_2Do") ] public interface IPerson { [OperationContract()] Person SetCustomer(List info); } 

3)客户端代码如下:

 PersonProxy p = new PersonProxy(); p.Guid = Guid.NewGuid(); p.First = txtFirst.Text; p.Last = txtLast.Text; p.Email = txtEmail.Text; p.Phone = txtPhone.Text; p.Site = txtSite.Text; var list = new List(); list.Add(p); 

最后,如果您真的需要在服务代码中使用Dictionary,则可以使用方法ToDictionary轻松转换List