在 .NET Compact Framework 中使用 WCF






4.76/5 (13投票s)
本文将向您展示如何从 PDA 设备创建 WCF Web 服务的代理客户端。

引言
创建各种 Web 服务时,我们可以非常轻松地以各种方式为 PC 创建客户端代理:可以通过 Visual Studio 中的“添加服务引用”工具,或者简单地通过命令行svcutil.exe设置参数,最后得到代码和配置文件。但是,如果我们业务涉及 Pocket PC 或 Smartphone 等便携式设备怎么办?幸运的是,这个问题有解决方案,我将在本文中进行介绍。
问题的解决方案
例如,我们将在 Visual Studio 2008 中创建新的 WCF Web 服务 - **文件 -> 新建 -> 项目 -> Web -> WCF 服务应用程序**,命名为BooksService
。然后,在创建了必要的数据类型和函数后,我们启动 Web 服务。它可能在 IIS 6.0/7.0 或 VS2008 内置的 ASP.NET 开发服务器中运行。那么,现在可以提出一个公平的问题——我们如何从掌上电脑连接到我们的服务?幸运的是,无需编写自己的代理类,有一种更简单的方法,那就是使用实用程序netcfsvcutil.exe,您可以从此链接下载。然后,我们在给定实用程序的参数中设置下一行:“http://192.168.134.10:8888/BooksService.svc”。退出后,我们将获得两个文件:CFClientBase.cs和BooksServie.cs。这正是我们需要的。现在,我将详细介绍服务创建及其便捷的移动客户端的创建。
WCF 服务
创建此 Web 服务后,我们将其接口声明如下:
[ServiceContract]
public interface IBooksService
{
[OperationContract]
string[] GetBookNames();
[OperationContract]
Book[] GetBooks(GetBookType type, string input);
[OperationContract]
Book[] GetAllBooks();
// TODO: Add your service operations here
}
正如您所见,代码中使用的类是Book
。其实现如下:
[DataContract]
public class Book
{
[DataMember]
public string Name { get; set; }
[DataMember]
public string Author { get; set; }
[DataMember]
public string ISBN { get; set; }
[DataMember]
public decimal Price { get; set; }
[DataMember]
public string Description { get; set; }
}
public enum GetBookType
{
ISBN, Name, Author
}
但是服务在哪里获取这些关于书籍的信息呢?为了不使示例复杂化,我们将在App_Data文件夹中内置一个 XML 文件data.xml来存储我们的数据,而不是处理 SqlServer 或 Oracle 等数据库。
<Books>
<Book>
<Name>Data Access and Web Services for Rich Internet Applications</Name>
<Author>John Papa</Author>
<ISBN>0-596-52309-2</ISBN>
<Price>44,99</Price>
<Description>This comprehensive bookl teaches you how to build
data-rich business applications with Silverlight 2 that draw on
multiple sources of data. Packed with reusable examples,
Data-Driven Services with Silverlight 2 covers all of the data access
and web service tools you need, including data binding, the LINQ
data querying component, RESTful and SOAP web service support,
cross-domain web service calls, and Microsoft's new ADO.NET Data Services
and the ADO.NET Entity Framework.</Description>
</Book>
...
<Books>
IBooksService
接口的实现如下:
public class BooksService : IBooksService
{
XDocument document = XDocument.Load(String.Format("{0}\\{1}\\{2}",
HostingEnvironment.ApplicationPhysicalPath, "App_Data",
"data.xml")); //getting path to the web service location and data file
public string[] GetBookNames()
{
var q = from dest in document.Root.Elements("Book")
select dest.Element("Name").Value; //return only name
return q.ToArray();
}
public Book[] GetBooks(GetBookType type, string input)
{
switch (type)
{
case GetBookType.ISBN: //if user select "ISBN" filter
{
var q = from dest in document.Root.Elements("Book")
where dest.Element("ISBN").Value ==
input //Strict comparison of the "ISBN" data
select new Book()
{
Author = dest.Element("Author").Value,
Description = dest.Element("Description").Value,
ISBN = dest.Element("ISBN").Value,
Name = dest.Element("Name").Value,
Price = Convert.ToDecimal(dest.Element("Price").Value)
};
return q.ToArray();
}
case GetBookType.Author: //if user select "Author" filter
{
var q = from dest in document.Root.Elements("Book")
where dest.Element("Author").Value.ToLower().
IndexOf(input.ToLower()) != -1 //Change of the
//register on lower and search of
//occurrence of a line "input"
//in an initial line
select new Book()
{
Author = dest.Element("Author").Value,
Description = dest.Element("Description").Value,
ISBN = dest.Element("ISBN").Value,
Name = dest.Element("Name").Value,
Price = Convert.ToDecimal(dest.Element("Price").Value)
};
return q.ToArray();
}
case GetBookType.Name: //if user select "Author" filter
{
var q = from dest in document.Root.Elements("Book")
where dest.Element("Name").Value.ToLower().
IndexOf(input.ToLower()) != -1 //Change of the
//register on lower and search of
//occurrence of a line "input" in an initial line
select new Book()
{
Author = dest.Element("Author").Value,
Description = dest.Element("Description").Value,
ISBN = dest.Element("ISBN").Value,
Name = dest.Element("Name").Value,
Price = Convert.ToDecimal(dest.Element("Price").Value)
};
return q.ToArray();
}
default:
{
return new List().ToArray();
}
}
}
public Book[] GetAllBooks()
{
var q = from dest in document.Root.Elements("Book") //return all books
select new Book()
{
Author = dest.Element("Author").Value,
Description = dest.Element("Description").Value,
ISBN = dest.Element("ISBN").Value,
Name = dest.Element("Name").Value,
Price = Convert.ToDecimal(dest.Element("Price").Value)
};
return q.ToArray();
}
}
您可以看到,我使用 LINQ to XML 处理 XML 数据,因为这对我来说是最简单的方法。现在,我们有了现成的服务,可以将其部署到任何托管上并连接到指定地址。因此,我们将开始最有趣的部分——为其创建掌上客户端。
PDA 客户端
首先,您应该创建一个新的**智能设备项目**。之后,您将获得一个新的空窗体及其自动创建的初始化代码。目前可以暂停。正如我在“问题解决方案”部分所说,您应该运行netcfsvcutil.exe并使用所需的参数启动。您应该将CFClientBase.cs和BooksService.cs文件添加到当前项目中。现在您已经拥有了现成的代理类。让我们看看如何正确初始化与我们服务的连接。
private void button1_Click(object sender, EventArgs e)
{
try
{
string remoteAddress = HelpClass.BuildUrl(); //get address
EndpointAddress endpoint = new EndpointAddress(remoteAddress);
client = new BooksServiceClient(new BasicHttpBinding(),
endpoint); //create new client proxy
comboBox1.Items.Clear();
foreach (string s in client.GetBookNames())
{
comboBox1.Items.Add(s);
}
books.Clear();
books.AddRange(client.GetAllBooks()); //get all names of the books
seed = 0;
if (books.Count > 1)
button1.Enabled = true;
comboBox1.SelectedIndex = 0;
}
catch (Exception ex) { MessageBox.Show(string.Format
("Connection Error: {0}", ex.Message)); }
}
已使用HelpClass
类
public static class HelpClass
{
static XDocument doc = XDocument.Load
(Assembly.GetExecutingAssembly().GetName().CodeBase.Substring(0,
Assembly.GetExecutingAssembly().GetName().CodeBase.LastIndexOf('\\') + 1) +
"settings.xml");
public static string BuildUrl()
{
return string.Format("http:/ /a{0}:{1}/BooksService.svc",
doc.Root.Element("Host").Value, doc.Root.Element("Port").Value);
}
}
因此,在连接到终结点后,您可以全面使用 Web 服务提供的所有功能。
结论
总而言之,正如您所看到的,创建服务的简单客户端并不需要特殊的技巧。所有代理创建的基本工作都由实用程序netcfsvcutil.exe承担,您的责任是提供服务地址并使用basicHttp
绑定初始化客户端。祝您好运!

历史
- 2009 年 6 月 14 日:初次发布