码迷,mamicode.com
首页 > 其他好文 > 详细

Wcf初体验

时间:2021-05-24 16:39:21      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:name   end   click   mes   从入门到放弃   catch   led   mini   alt   

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="DEVELOPER\Administrator" />
                </identity>
            </endpoint>
        </client>
    </system.serviceModel>

到这里就结束了

Wcf初体验

标签:name   end   click   mes   从入门到放弃   catch   led   mini   alt   

原文地址:https://www.cnblogs.com/AduBlog/p/14785995.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!