zoukankan      html  css  js  c++  java
  • Silverlight WCF 封装尝试

       研究silverlight wcf陆陆续续有一段时间了,由于一直不太适应传统的引用做法,所以想封装出一个简单的方法进行silverlight 和wcf之间通讯。

    大家都知道,如果是控制台程序或者是winform程序,在程序中要发布一个wcf很简单,可以开辟一个线程,在登录或者主窗口初始化的时候把服务开启即可,

    但是对于silverlight比较特殊,程序已启动,就直接加载SL客户端,在启动的时候,在服务端要做一些事情不太容易,而你等silverlight再想做服务端的事情时,

    就没那么简单了,必须要用通讯。

      传统的wcf引用的方法是,在web目录新建一个wcf服务,会自动生成一个svc文件和一个对应的服务接口,右键svc文件,选择在浏览器中运行,然后再SL客户端

    现在引用服务,弹出窗口中点发现,然后会自动生成一个客户端,和配置文件。然后再客户端使用的时候创建客户端实例,然后再调用同步方法和方法回调。这种方

    法不易于维护和管理,工作起来也挺别扭。所以,我决定封装起来,尽量把这个通道简化一点。

    下面是项目的结构

    一:服务端Service

     有2个服务,每个服务分别一个接口

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;
    namespace Service
    {
        [ServiceContract]
        public interface ITestService
        {
            [OperationContract]
            void DoWork();
        }
    }
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Service
    {
        public class TestService : ITestService
        {
            public void DoWork()
            {
                
    
            }
        }
    }
    

     第二个接口和实现,返回字符串

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;
    namespace Service
    {
        [ServiceContract]
        public interface ITestService2
        {
            [OperationContract]
            string GetData(string str);
        }
    }
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Service
    {
        public class TestService : ITestService
        {
            public void DoWork()
            {
                
    
            }
        }
    }

    OK,服务端定义和实现就这些,

       然后看web项目怎么配置吧,首先先把服务类库引用过来,然后添加两个wcf,名称和服务实现类名一致,把自动生成的接口文件删除,以及.cs文件也删除,然后双击打开svc文件,改成如下配置。

    如果没有需求,web层的工作到此就结束了。最后看客户端是怎么实现的,客户端有2个异步服务接口,其实,通用引用方式引用服务的时候,也会自动生成对应的接口,一个开始begin,和一个结束end,不过,我在这里给服务特性加了一个configname属性,用来匹配svc文件,所以ConfigurationName要等于你的svc文件名一致,看下面的代码吧。

    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using System.ServiceModel;
    namespace Service
    {
        [ServiceContract(ConfigurationName = "TestService")]
        public partial interface ITestService
        {
            [OperationContract(AsyncPattern = true)]
            IAsyncResult BeginDoWork(AsyncCallback callback, object state);
            void EndDoWork(IAsyncResult result);
        }
    }
    
    using System;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Ink;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using System.ServiceModel;
    namespace Service
    {
        [ServiceContract(ConfigurationName = "TestService2")]
        public partial interface ITestService2
        {
            [OperationContract(AsyncPattern = true)]
            IAsyncResult BeginGetData(string str, AsyncCallback callback, object state);
            string EndGetData(IAsyncResult result);
        }
    }
    

     客户端定义就到此结束,最后还剩下一个使用wcf,留到最后讲,下面看代理类,客户端只要传递服务接口,就可以返回一个代理类实例,然后使用服务的开始方法和结束方法,

    using System;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Ink;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.Linq;
    namespace Proxy
    {
        public class Proxy
        {
            /// <summary>
            /// 根据接口创建一个wcf接口实例
            /// </summary>
            /// <typeparam name="T">服务接口</typeparam>
            /// <returns>接口实例</returns>
            public static T GetService<T>()
            {
    
                var xapUri = Application.Current.Host.Source;
                //web路径
                var webUri = new Uri(xapUri, "../");
                string webpath = webUri.ToString();
                Type type = typeof(T);
                //wcf服务全路径
                string url = "";
    
                //获取接口契约的特性
                object[] atbs = type.GetCustomAttributes(typeof(ServiceContractAttribute), false);
                if (atbs.Any(cp => cp.GetType() == typeof(ServiceContractAttribute)))
                {
                    ServiceContractAttribute abt = atbs.First(cp => cp.GetType() == typeof(ServiceContractAttribute)) as ServiceContractAttribute;
                    string servicepath = abt.ConfigurationName;
                    url = webpath + servicepath;
                }
    
                //生成接口实例
                if (!string.IsNullOrEmpty(url))
                {
                    EndpointAddress epAddress = new EndpointAddress(url + ".svc");
                    Binding binding = new BasicHttpBinding();
                    ChannelFactory<T> factory = new ChannelFactory<T>(binding, epAddress);
                    T client = factory.CreateChannel();
                    return client;
                }
                else
                    return default(T);
            }
        }
    }
    

     在客户端项目中,把这个代理类库引用进来,就可以使用了,使用代码如下

     private void button1_Click(object sender, RoutedEventArgs e)
            {
                ITestService client = Proxy.Proxy.GetService<ITestService>();
                client.BeginDoWork((result) =>
                {
                    Deployment.Current.Dispatcher.BeginInvoke(() => { MessageBox.Show("第一个服务执行完毕"); });
                }, null);
    
    
                ITestService2 client2 = Proxy.Proxy.GetService<ITestService2>();
                client2.BeginGetData("123", (result) =>
                {
                    Deployment.Current.Dispatcher.BeginInvoke(() => { MessageBox.Show(client2.EndGetData(result)); });
                }, null);
            }
    

     

    到此,这个工作就结束了。

    这样做的好处就是,你不需要面对一堆的配置文件,只需要定义接口和实现,也易于再次对接口的封装,使用起来也方便,只要对代理类传递接口就可以得到一个服务实例,不用关心服务如何配置,如何实现。总之,我觉得还挺适合我,不知道对各位有没有用,欢迎大家来讨论和拍砖!!! 最后感谢一些一个叫“飞”的网友,他帮我解决了一些谜团。

  • 相关阅读:
    java中的abstract、接口、final和Object
    java中的多态性
    java中的继承和覆盖
    面向对象编程
    java中的this
    java中的类与对象(2)
    java中的类与对象(1)
    Java中的运算及优先级
    Selenium Python
    Python学习①. 基础语法
  • 原文地址:https://www.cnblogs.com/Rmeo/p/3230560.html
Copyright © 2011-2022 走看看