契约操作不能使用引用对象作为参数,只允许使用基本类型或数据契约
今天看了一下wcf服务编程这本书,本来准备大致的浏览一下,但是当我看到了契约操作不能使用引用对象作为参数,只允许使用基本类型或数据契约这句话的时候,我知道契约操作只能是通过数据契约进行数据的传递,但是我也是好奇在电脑上测试了一下,结果发现这句话存在问题,可能是我对这句话的理解不够,或者说这句话隐含着什么别的意思,我没有理解透,下面我们就一起来通过这句话来构建一个测试程序来测试一下这句话的正确性。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.ServiceModel; 6 using System.Runtime.Serialization; 7 namespace Chinaer.WcfDemo.Contracts 8 { 9 public class BookInfo 10 { 11 public string Title { get; set; } 12 13 public string Name { get; set; } 14 } 15 16 17 [ServiceContract( Namespace = "http://chinaer.com")] 18 public interface IBook 19 { 20 [OperationContract] 21 List<BookInfo> GetBooks(BookInfo info); 22 23 [OperationContract] 24 void Check(string strMessage); 25 } 26 }
我们首先定义了一个服务契约IBook,然后定义了一个实体类BookInfo,定义了一个方法GetBooks,其中参数为BookInfo类型,我们之所以这样定义是因为契约操作不能使用引用对象作为参数,只允许使用基本类型或数据契约 这句话中不能使用引用对象,而我们使用了一个类的对象,属于引用对象的范畴。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.ServiceModel; 6 using Chinaer.WcfDemo.Contracts; 7 namespace Chinaer.WcfDemo.Services 8 { 9 [ServiceBehavior()] 10 public class BookService : IBook 11 { 12 public List<BookInfo> GetBooks(BookInfo bookInfo) 13 { 14 List<BookInfo> listBooks = new List<BookInfo>(); 15 for (int i = 0; i < 100; i++) 16 { 17 BookInfo info = new BookInfo() { Title=i.ToString(), Name="name"+i.ToString() }; 18 listBooks.Add(info); 19 } 20 return listBooks; 21 } 22 23 public void Check(string strMessage) 24 { 25 bool flag = false; 26 if (strMessage.Equals("guozhiqi", StringComparison.OrdinalIgnoreCase)) 27 { 28 flag = true; 29 } 30 } 31 } 32 }
在服务类中我们实现了契约的方法,这其中没有什么要介绍的。
下一步就是托管代码的实现。
1 <?xml version="1.0" encoding="utf-8" ?> 2 <configuration> 3 <system.serviceModel> 4 <services> 5 <service name="Chinaer.WcfDemo.Services.BookService"> 6 <endpoint bindingConfiguration="securityMode" 7 address="http://192.168.1.106:88/bookService" 8 binding="wsHttpBinding" 9 contract="Chinaer.WcfDemo.Contracts.IBook"></endpoint> 10 </service> 11 </services> 12 13 <bindings> 14 <wsHttpBinding> 15 <binding name="securityMode"> 16 <security mode="None"></security> 17 </binding> 18 </wsHttpBinding> 19 </bindings> 20 21 <behaviors></behaviors> 22 23 </system.serviceModel> 24 25 </configuration>
1 using (ServiceHost guoHost = new ServiceHost(typeof(BookService))) 2 { 3 4 // Chinaer.WcfDemo.Contracts.IGuo 5 if (guoHost.Description.Behaviors.Find<ServiceMetadataBehavior>() == null) 6 { 7 ServiceMetadataBehavior metaDataBehavior = new ServiceMetadataBehavior(); 8 metaDataBehavior.HttpGetEnabled = true; 9 metaDataBehavior.HttpGetUrl = new Uri("http://192.168.1.106:883/mex"); 10 guoHost.Description.Behaviors.Add(metaDataBehavior); 11 } 12 guoHost.Opened += delegate { Console.WriteLine("bookService Open"); }; 13 try 14 { 15 if (guoHost.State != CommunicationState.Opened || guoHost.State != CommunicationState.Opening) 16 { 17 guoHost.Open(); 18 int i = 0; 19 foreach (ChannelDispatcher channelDispatcher in guoHost.ChannelDispatchers) 20 { 21 Console.WriteLine("{0}:{1}", ++i, channelDispatcher.Listener.Uri); 22 } 23 Console.Read(); 24 } 25 } 26 catch (CommunicationException ex) 27 { 28 guoHost.Abort(); 29 } 30 catch (Exception ex) 31 { 32 guoHost.Abort(); 33 }
在托管程序启动以后我们就需要在客户端通过终结点访问服务,请注意我们传递的参数类型为BookInfo的实例,并不是数据契约
下面是客户端实例,其实这种过程都是老一套,只不过是更改了属性或者说是要测试特定的知识点。
1 //ServiceReference3.BookClient client = new ServiceReference3.BookClient(); 2 //BookInfo info = new BookInfo(); 3 //BookInfo[] arrinfo = client.GetBooks(info); 4 5 using (ChannelFactory<IBook> chann = new ChannelFactory<IBook>("WSHttpBinding_IBook")) 6 { 7 IBook book = chann.CreateChannel(); 8 using (book as IDisposable) 9 { 10 BookInfo[] arrInfo = book.GetBooks(new BookInfo()); 11 Console.Read(); 12 } 13 14 }
这就说明刚才wcf服务编程上那句话是错误的,可能是我没有真正的理解那句话的真正含义,如果你知道这句话应该如何解释,麻烦你告诉我,谢谢。
有人的地方就有政治,有政治就有斗争,但我讨厌政治,讨厌无休止的迎合。