• Wcf初体验


    Wcf项目代码结构如下:

    Book.Common:公共类库,提供公共方法。类库

    Book.Models:提供实体类。类库

    Book.WcfService:Wcf接口以及实现。类库

    Book.WinForm:显示获取信息。winForm窗体

    Hosting:服务宿主,将Wcf服务承载到一个进程中。控制台程序

    Book.WcfService定义IBookService和BookService

    [ServiceContract]
        public interface IBookService
        {
            [OperationContract]
            string GetBook(string bookId);
        }

    需要引用System.ServiceModel。Wcf是基于契约的,这里将接口类声明为服务契约,方法生命为操作契约

    public class BookService : IBookService
        {
            public string GetBook(string bookId)
            {
                Books book = GetBookById(bookId);
                string xml = XmlHelper.ToXml<Books>(book);
                return xml;
            }
    
            public Books GetBookById(string id)
            {
                Books book = new Books();
                book.Name = "C#从入门到放弃";
                book.Price = 54;
                book.AuthorId = 1;
                return book;
            }
        }

    以上是接口的实现。

    上面需要引用Books类

    在Book.Models类库里面声明

    [DataContract]
        public class Books
        {
            [DataMember]
            public string Name { get; set; }
    
            [DataMember]
            public int Price { get; set; }
    
            [DataMember]
            public int AuthorId { get; set; }
        }

    公共方法类XmlHelper包含在Book.Common里

    public class XmlHelper
        {
            /// <summary>
            /// 反序列化成对象
            /// </summary>
            /// <typeparam name="T">对象类型</typeparam>
            /// <param name="filename">XML文件路径</param>
            /// <returns></returns>
            public static T ParseXml<T>(string filename)
            {
                T obj = default(T);
                XmlSerializer serializer = new XmlSerializer(typeof(T));
                FileStream fs = new FileStream(filename, FileMode.Open);
                try
                {
                    obj = (T)serializer.Deserialize(fs);
                }
                catch (System.Exception ex)
                {
                    string s = ex.Message;
                    throw ex;
                }
                finally
                {
                    fs.Close();
                }
                return obj;
            }
    
            /// <summary>
            /// 反序列化成对象
            /// </summary>
            /// <param name="filename">XML文件路径</param>
            /// <param name="type">对象类型</param>
            /// <returns></returns>
            public static object ToObject(string filename, Type type)
            {
                object obj;
                XmlSerializer serializer = new XmlSerializer(type);
                FileStream fs = new FileStream(filename, FileMode.Open);
                try
                {
                    obj = serializer.Deserialize(fs);
                }
                catch (System.Exception ex)
                {
                    string s = ex.Message;
                    throw ex;
                }
                finally
                {
                    fs.Close();
                }
                return obj;
            }
    
    
    
            /// <summary>
            /// 反序列化成对象
            /// </summary>
            /// <typeparam name="T">对象类型</typeparam>
            /// <param name="data">XML数据对象字符串</param>
            /// <returns></returns>
            public static T DeSerializer<T>(string data)
            {
                T obj = default(T);
                XmlSerializer serializer = new XmlSerializer(typeof(T));
                try
                {
                    using (StringReader sr = new StringReader(data))
                    {
                        XmlSerializer xz = new XmlSerializer(typeof(T));
                        obj = (T)serializer.Deserialize(sr);
                    }
                }
                catch (System.Exception ex)
                {
                    string s = ex.Message;
                    throw ex;
    
                }
                return obj;
            }
    
            /// <summary>
            /// 创建XML文件
            /// </summary>
            /// <param name="fullFileName">XML文件名</param>
            /// <param name="data">XML字符串</param>
            public static void CreateXml(string fullFileName, string data)
            {
                using (StreamWriter sw = new StreamWriter(fullFileName, false, Encoding.UTF8))
    
                {
                    sw.Write(data);
                }
            }
    
            /// <summary>
            /// 把对象转换成字符串
            /// </summary>
            /// <typeparam name="T">对象类型</typeparam>
            /// <param name="t">对象实体</param>
            /// <returns></returns>
    
            public static string ToXml<T>(T t)
            {
                using (StringWriter sw = new StringWriter())
                {
                    XmlSerializer xz = new XmlSerializer(t.GetType());
                    xz.Serialize(sw, t);
                    return sw.ToString();
                }
            }
        }

    上述服务需要一个宿主来承载,他不会自主运行。Wcf给予终结点(EndPoint)的手段进行通信

    在Hosting的配置文件App.config中的configuration中添加声明

    <system.serviceModel>
            <behaviors>
                <serviceBehaviors>
                    <behavior name="metadataBehavior">
                        <serviceMetadata httpGetEnabled="true" httpGetUrl="http://127.0.0.1:8888/BookService/metadata" />
                    </behavior>
                </serviceBehaviors>
    
            </behaviors>
            <services>
                <service  behaviorConfiguration="metadataBehavior" name="Book.WcfService.BookService">
                    <endpoint address="http://127.0.0.1:8888/BookService"
                        binding="wsHttpBinding" bindingConfiguration="" contract="Book.WcfService.IBookService" />
                </service>
            </services>
        </system.serviceModel>

    上面可以看到终结点Endpoint是由地址Address、绑定Binding和契约contract组成,也就是EndPoint=ABC

    WCF服务的描述通过元数据(Metadata)的形式发布出来。

    上面的配置我们声明了元数据的获取地址,

    在Hosting的Program.cs中声明

    using (ServiceHost host = new ServiceHost(typeof(BookService)))
                    {
    
                        //服务打开时发生
                        host.Opened += delegate
                        {
                            Console.WriteLine("BookService 按任意键结束");
                        };
    
                        host.Open();
    
                        Console.ReadKey();
                    }

    此时到文件夹中运行Hosting.exe 注意使用管理员身份运行。不然会报错

    那么浏览器输入http://127.0.0.1:8888/BookService/metadata 就可以看到元数据了

    运行Hosting的情况下,在Book.WinForm的引用 右键 添加服务引用

    如上添加服务

    在Book.WinForm的点击事件上添加

    private void button1_Click(object sender, EventArgs e)
            {
                Books book = new Books();
                BookServiceRef.BookServiceClient client = new BookServiceRef.BookServiceClient();
    
                msgBox.Text = client.GetBook("1");
                book=XmlHelper.DeSerializer<Books>(msgBox.Text);
                textBox1.Text = book.Name;
                textBox2.Text = book.Price.ToString();
                textBox3.Text = book.AuthorId.ToString();
            }

    结果如图

    上述方法是采用继承与ClientBase<T>的对象进行服务调用,也就是这里的BookServiceRef。换一种方式呢?

    关键在于我们要找到获取书籍信息的方法,也就是GetBook,显然Winform窗体程序不能直接引用Book.WcfService,这样所有的内容都暴露了,没有意义

    那么可以新建一个类库,用来放接口IBookService

    新建Book.Contracts类库

    将IBookService粘贴到里面,让Book.WcfService和Book.WinForm引用它

    将原来Book.WinForm的服务引用删除

    将点击事件换成

    using(ChannelFactory<IBookService> channelFactory=new ChannelFactory<IBookService>("ws_IBookService"))
                {
                    Books book = new Books();
                    IBookService proxy = channelFactory.CreateChannel();
    
                    using(proxy as IDisposable)
                    {
                        msgBox.Text = proxy.GetBook("1");
                        book = XmlHelper.DeSerializer<Books>(msgBox.Text);
                        textBox1.Text = book.Name;
                        textBox2.Text = book.Price.ToString();
                        textBox3.Text = book.AuthorId.ToString();
                    }
                } 

    在Book.WinForm的配置里添加

    <system.serviceModel>
            <bindings>
                <wsHttpBinding>
                    <binding name="WSHttpBinding_IBookService" />
                </wsHttpBinding>
            </bindings>
            <client>
                <endpoint address="http://127.0.0.1:8888/BookService" binding="wsHttpBinding"
                    bindingConfiguration="WSHttpBinding_IBookService" contract="Book.Contracts.IBookService"
                    name="ws_IBookService">
                    <identity>
                        <userPrincipalName value="DEVELOPERAdministrator" />
                    </identity>
                </endpoint>
            </client>
        </system.serviceModel>

    到这里就结束了

    记录编程的点滴,体会学习的乐趣
  • 相关阅读:
    2020.4.21 考试T1 HDU 5729
    BZOJ 4198: [Noi2015]荷马史诗
    BZOJ 1052: [HAOI2007]覆盖问题
    BZOJ 1087: [SCOI2005]互不侵犯King
    BZOJ 4466 线性函数
    Linux如何挂载U盘
    集中式日志分析平台
    ELK5.2+kafka+zookeeper+filebeat集群部署
    浅析ES的_source、_all、store、index
    IndexOf、LastIndexOf、Substring的用法
  • 原文地址:https://www.cnblogs.com/AduBlog/p/14785995.html
Copyright © 2020-2023  润新知