WCF for .NET CF快速入门

转载文章介绍:其实在智能设备上至少有两种方法调用wcf服务,一种是直接在smart project中引用web service,然后就可以了。其优点是快捷方便,但最大的缺点是wcf服务地址被硬编码了,更新地址需要重新编译。(如有不对请拍砖)

另外一种就是下面转载的文章,使用netcfSvcUtil生成客户端代码,然后从配置文件中加载配置信息,避免了上述的问题。至于加载xml配置文件(compact framework 没有提供现成的ConfigurationManager)的方法可参考文章:http://blogs.freshlogicstudios.com/Posts/View.aspx?Id=2a18bfe7-caec-467d-913c-597627e92247

 

转自:http://www.cnblogs.com/fox23/archive/2008/03/18/translate-wcf-for-device-developers.html

 

 

摘要
本文可以看作是Chris Tacke的文章An Introduction to WCF for Device Developers的翻译,文中代码由于笔者调试需要稍作了修改,局部做了进一步的说明,并将部分链接更新。
Keyword
Windows Mobile, WCF, .NET CF, Services, Xml Serialization

这是一篇我推荐给很多朋友看过的文章。文章很短,也没有涉及太多WCF原理性的东西,但是作为WCF Mobile开发入门,这却是个很好的向导,为了方便阅读,有些地方我做了额外的说明。
Enjoy it~

开发环境与工具

1. Visual Studio 2008 (Orcas) RTM. 
2. Power Toys for .NET Compact Framework 3.5
3. 一台 支持.NET Compact Framework3.5的Windows Mobile 5.0/6.0 的模拟器或者设备. 
(Chris Tacke在他的设备上调试成功,在模拟器上由于某些不可知的因素失败了。笔者在模拟器上调试成功)
4. Windows XP 或者 Vista的操作系统
(Chris Tacke在XP下调试的,笔者则是在Vista下)

2 PC
端的WCF服务程序

当然,这只是一个很简单的模型,就是通过WCF使移动设备与PC进行信息交互。
首先,我们需要在PC机上构建一个服务,这个服务实现的功能很简单,就是进行两个整数的加法,并返回结果。
第一步,打开你的VS创建一个控制台程序,并添加引用:System.ServiceModel
然后,添加一个新的类(事实上是一个接口,它用于定义我们的服务所暴露出来的契约),我们把这个类命名为IMyProcess,其内容如下:

using  System.ServiceModel;
namespace  Freesc.WCF.Demo
{
        [ServiceContract(Namespace = http://Freesc.WCF.Demo)]
       public interface IMyProcess
        {
            [OperationContract]
            int Add(int a, int b);
        }

}

接下来,我们需要一个该借口的具体实现来作为我们的服务。为我们的工程另添加一个类,叫做MyProcessService,也就只包含一个Add方法。其代码如下:

using  System;

namespace  Freesc.WCF.Demo
{
 public class MyProcessService:IMyProcess
    {
      public int Add(int a, int b)
      {
          Console.WriteLine(string.Format(
          "Received 'Add({0}, {1})' returning {2}", a, b, a + b));
          return a + b;
      }

    }

}

好,服务的内容已经写好了,我们需要来看看这个PC端的Server是怎么工作的了。首先,请将你的Program.cs替换为如下代码:

using  System;
using  System.ServiceModel;
using  System.ServiceModel.Description;
using  System.Net;

namespace  Freesc.WCF.Demo
{
    class Program
    {
        static void Main(string[] args)
        {
          //获得服务器IP
            string hostIP = Dns.GetHostEntry(Dns.GetHostName()).AddressList[2].ToString();
#if CLIENT_DISCOVERY_BUILD
          Uri address = new Uri(string.Format("http://localhost:8000/calculator", hostIP));
#else
          Uri address = new Uri(string.Format("http://{0}:8000/calculator", hostIP));
#endif
            ServiceHost serviceHost = new ServiceHost(typeof(MyProcessService), address);
            try
            {
                // 添加一个服务节点
                serviceHost.AddServiceEndpoint(
                    typeof(IMyProcess),
                    new BasicHttpBinding(),
                    "Calculator");
#if !CLIENT_DISCOVERY_BUILD
                // 允许运行时的元数据交互(使用NetCfSvcUtil工具)
                ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
                smb.HttpGetEnabled = true;
                serviceHost.Description.Behaviors.Add(smb);
#endif
                serviceHost.Open();
                Console.WriteLine("MyProcessService is running at " + address.ToString());
                Console.WriteLine("Press <ENTER> to terminate");
                Console.ReadLine();
                // 把服务状态置为关闭
                serviceHost.Close();
            }

            catch (CommunicationException ce)
            {
                Console.WriteLine("An exception occured: {0}", ce.Message);
                serviceHost.Abort();
            }

        }

    }

}


这段程序要稍稍复杂一点,首先,你也许会注意到这里用了一些预编译指令。使用这些预编译指令是因为我们要在稍后的一个工具中访问这个运行的服务并为我们生成一些代码。如果你暂时还比较晕的话,别急,稍后会说到这个工具的。

这里的CLIENT_DISCOVERY_BUILD只是一个条件编译的符号,您暂且可以无视之。其实这里只是为了我们编译代码的时候版本切换比较方便。

某些情况下我们希望把前面编译的A版本的代码暂存起来,以免在CS文件中该来改来改去,这时只需要在Debug 的配置项目下做一些修改,比如这里我们加上了Discover这一项,用记事本打开工程文件,可以看到这一段:

< PropertyGroup  Condition =" '$(Configuration)|$(Platform)' == 'Discovery|AnyCPU' " >
     < DebugSymbols > true </ DebugSymbols >
     < OutputPath > bin"Discovery" </ OutputPath >
     < DefineConstants > TRACE;DEBUG;CLIENT_DISCOVERY_BUILD </ DefineConstants >
     < DebugType > full </ DebugType >
     < PlatformTarget > AnyCPU </ PlatformTarget >
     < ErrorReport > prompt </ ErrorReport >
  </ PropertyGroup >

好,那这一段主程序代码到底有什么作用呢?首先,我们需要为我们的服务创建一个Uri。

要创建这个Uri首先要知道本机的IP。这里如果你直接Copy Chris Tacke的代码也许不能运行(特别是Vista用户),可能会抛出一个这样的异常:

这个时候你需要检查你的IPAddress的AddressFamily,或者直接CMD下察看ipconfig,如果是IPV6的话(如我机器上的AddressList[0]就是iPV6的格式),则会抛除上述异常,iPv4则一切OK。

接下来,我们创建了一个服务主机(ServiceHost)和一个服务节点(endpoint),请注意,这里我们用的协议绑定方式是BasicHttpBinding,在精简版的WCF framework中默认只有两种绑定绑定方式(另一种是WindowsMobileMailBinding,我在今后的文章中会介绍)。然后我们给服务起了个名字叫做“Calculator”。

接下来,可以看到我们先前提到过的条件编译符号,在我们开启Discovery的配置环境下,我们的工具(下文会提到)可以与该程序集的元数据进行交互用来生成一些代码,不过上面的代码里是处于关掉的模式。

好了,现在可以来试着编译这段代码了,编译的时候请确保在Discover的模式下。

如果一切OK,你将会看到如下的画面:

注意:如果是Vista用户,如果开启了UAC,你可能需要以管理员的身份运行编译好的可执行程序,否则可能会有某些权限问题。

然后,我们在浏览器中键入这里显示的地址,可以看到如下画面

如果你的确看到上述页面,很好,我们的工作已经完成一半了。

3. NetCFSvcUtil.exe

下面我们需要借助一个小工具---netcfSvcUtil来帮助我们生成一些代码,这个方法适用于那些初次进行WCF for Mobile编程的人,或者是象我这样比较懒,比较喜欢使用小工具的程序员。

打开你的命令行工具,你的Power Toy默认安装在类似这样的目录下:
C:"Program Files"Microsoft.NET"SDK"CompactFramework"v3.5"bin.

在之前的服务运行的时候,在该目录下运行如下的命令:

netcfSvcUtil.exe /language:cs http://localhost:8000/calculator

你可以看到如图的输出:

此时你会发现在该目录下生成了两个CS文件,这里分别是MyProcessService.cs和CFClientBase.cs
在接下来的步骤中,我们会用到这两个文件。

4. CF端的应用程序

接下来,我们新建一个Smart Device 的窗体应用程序,工程命名为DeviceClient。将前面生成的那两个文件Copy到该工程中来,然后,我们得添加如下一些引用(主要是那两个由工具生成的cs文件需要):

- System.ServiceModel

- System.Runtime.Serialization

这里的代码如下:

       public  Form1()
         {
            InitializeComponent();
            try
            {
//在TextBox中显示本机IP
                tbMyIP.Text = Dns.GetHostEntry(
                Dns.GetHostName()).AddressList[0].ToString();
            }

            catch (Exception ex)
            {
                MessageBox.Show("No NIC found?");
            }

        }

        private   void  menuCalculate_Click( object  sender, EventArgs e)
         {
            int a = 0;
            int b = 0;
            try
            {
//接受文本框的输入,并存入整形变量a,b中
                a = int.Parse(tbFirst.Text);
                b = int.Parse(tbSecond.Text);
            }

            catch
            {
                //如果转换失败(比如填入了无效的数字)则直接返回
                return;
            }

            SMC.Binding binding = MyProcessClient.CreateDefaultBinding();
            string remoteAddress = MyProcessClient.EndpointAddress.Uri.ToString();
            remoteAddress = remoteAddress.Replace("localhost", “192.168.1.101”);
            EndpointAddress endpoint = new EndpointAddress(remoteAddress);
            MyProcessClient client = new MyProcessClient(binding, endpoint);
            try
            {
                lbResult.Text = client.Add(a, b).ToString();
            }

            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

        }

代码很短,不过很重要的一点是我们没有使用DeviceClient的默认构造器,我们把RemoteAddress中的”localhost”替换成了服务所在主机的IP(你可以在MyProcessClient类的找到相应的静态字段)。

点击menuCalculate我们看到以下的结果:
PC机上

设备上


下载完整代码

总结

从上面的例子我们看到,在Windows Mobile上构建一个WCF的应用程序并不是太难,代码量也不大,只是我们缺少相应的文档资源, 也许本文能帮你节约一点上手的时间。

希望这篇短文能对大家有所帮助,尽管它并没有对某些细节做清楚的阐述,但是相信您已经能够按照文中的做法,在Windows Mobile上轻松构建出你自己的WCF程序,那么本文的目的也就达到了。

Regards
©Freesc Huang
  黄季冬<fox23>@HUST

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值