WCF一步一步往前爬(二)

來源:互聯網
上載者:User

第二步:

WCF宿主程式用哪種類型比較好? 主要的託管宿主包括,IIS,控制台程式,WPF,Windows Forms,NT Service,Windows服務,COM+作為宿主。IIS部署簡單,可以向發布Web Service一樣部署,但是僅僅支援HTML協議,而且宿主進程在客戶請求時候啟動。控制台作為宿主託管簡單,一般做簡單WCF 編程時候使用。Windows Forms宿主可以提供管理宿主狀態的UI,操作更加直觀。一般企業WCF宿主會採用Windows服務或者COM+,Windows服務可以長期運行在後台,支援所有的綁定協議,但是安裝部署相對複雜。COM+,作為宿主,我們可以利用COM+組建的一些特性,例如對象池等。 
一般企業開發選擇IIS,Windows服務,效能要求的時候可以考慮COM+,作為宿主。  個人學習IIS和控制台程式相對開發簡單,配置便捷。

在這裡我們實踐一把WCF宿主方式:IIS中的WAS(net.tcp),自己寫的wpf程式(http或net.tcp),windows服務(net.pipe)

 

IIS中的WAS(net.tcp)

1、確定Windows Process Activation Service在windows組件中已經安裝。

2、開啟IIS對於已經在第一步發布到IIS中的ProductsService服務,點擊“進階設定”在“已啟用的協議”設定“http,net.tcp”。

3、ProductsClient項目app.config.添加一個endpoint節點

<client>
<endpoint address="http://localhost/ProductsService/ProductsService.svc"
binding="basicHttpBinding"bindingConfiguration="BasicHttpBinding_IProductsService"
contract="ProductsService.IProductsService"name="BasicHttpBinding_IProductsService" />

<endpointaddress="net.tcp://localhost/ProductsService/ProductsService.svc"
binding="netTcpBinding"contract="ProductsService.IProductsService"
name="NetTcpBinding_IProductsService" />
</client>

IIS中WAS(net.tcp)中宿寄wcf服務就大功告成

 

wpf程式(http或net.tcp)

1、建立類庫ProductsServiceLibrary,引入NBuilder.dll。分別添加tblProduct.cs,tblProductInventory.cs,IProductsService.cs和ProductsService.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace ProductsServiceLibrary
{
    /// <summary>
    ///tblProduct 的摘要說明
    /// </summary>
    public class tblProduct
    {
        public tblProduct()
        {
            //
            //TODO: 在此處添加建構函式邏輯
            //
        }

        public int ProductID;

        public string Name;

        public string ProductNumber;

        /// <summary>
        /// 0 = 產品是購買的。1 = 產品是內部生產的。
        /// </summary>
        public bool MakeFlag;

        /// <summary>
        //0 = 產品不可銷售。1 = 產品可銷售。
        /// </summary>
        public bool FinishedGoodsFlag;

        public string Color;

        ////最小庫存量。
        public int SafetyStockLevel;

        /// <summary>
        /// 觸發採購訂單或工單的庫存水平。
        /// </summary>
        public int ReorderPoint;

        /// <summary>
        /// 產品的標準成本。
        /// </summary>
        public decimal StandardCost;

        /// <summary>
        /// 銷售價格。
        /// </summary>
        public decimal ListPrice;

        /// <summary>
        /// 產品的規格。
        /// </summary>
        public string Size;

        /// <summary>
        /// Size 列的測量單位。
        /// </summary>
        public string SizeUnitMeasureCode;

        /// <summary>
        /// Weight 列的測量單位。
        /// </summary>
        public string WeightUnitMeasureCode;

        /// <summary>
        /// 產品的重量。
        /// </summary>
        public decimal Weight;

        /// <summary>
        /// 生產產品所需的天數。
        /// </summary>
        public int DaysToManufacture;

        /// <summary>
        /// R = 平地 M = 山地 T = 旅行 S = 標準
        /// </summary>
        public string ProductLine;

        /// <summary>
        /// H = 高 M = 中 L = 低
        /// </summary>
        public string Class;

        /// <summary>
        /// W = 女式 M = 男式 U = 通用
        /// </summary>
        public string Style;

        /// <summary>
        /// 產品所屬的產品子類別。指向 ProductSubCategory.ProductSubCategoryID 的外鍵。
        /// </summary>
        public int ProductSubcategoryID;

        /// <summary>
        /// 產品所屬的產品型號。指向 ProductModel.ProductModelID 的外鍵。
        /// </summary>
        public int ProductModelID;

        /// <summary>
        /// 產品開始銷售的日期。
        /// </summary>
        public DateTime SellStartDate;

        /// <summary>
        /// 產品停止銷售的日期。
        /// </summary>
        public DateTime SellEndDate;

        /// <summary>
        /// 產品停產的日期。
        /// </summary>
        public DateTime DiscontinuedDate;

        /// <summary>
        /// 行的上次更新日期和時間。
        /// </summary>
        public DateTime ModifiedDate;
    }
}

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace ProductsServiceLibrary
{
    /// <summary>
    ///ProductInventory 的摘要說明
    /// </summary>
    public class tblProductInventory
    {
        public tblProductInventory()
        {
            //
            //TODO: 在此處添加建構函式邏輯
            //
        }

        /// <summary>
        /// 產品標識號。指向 Product.ProductID 的外鍵。
        /// </summary>
        public int ProductID;

        /// <summary>
        /// 庫存位置標識號。指向 Location.LocationID 的外鍵。
        /// </summary>
        public int LocationID;

        /// <summary>
        /// 庫存位置中的儲存間。
        /// </summary>
        public string Shelf;

        /// <summary>
        /// 庫存位置中架子上的儲存容器。
        /// </summary>
        public int Bin;

        /// <summary>
        /// 庫存位置中的產品數量。
        /// </summary>
        public int Quantity;

        /// <summary>
        /// 行的上次更新日期和時間。
        /// </summary>
        public DateTime ModifiedDate;
    }
}

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace ProductsServiceLibrary
{
    // 注意: 使用“重構”菜單上的“重新命名”命令,可以同時更改代碼和設定檔中的介面名“IService”。
    [ServiceContract]
    public interface IProductsService
    {

        // Get the product number of every product
        [OperationContract]
        List<string> ListProducts();
        // Get the details of a single product
        [OperationContract]
        ProductData GetProduct(string productNumber);
        // Get the current stock level for a product
        [OperationContract]
        int CurrentStockLevel(string productNumber);
        // Change the stock level for a product
        [OperationContract]
        bool ChangeStockLevel(string productNumber, short newStockLevel, string shelf, int bin);
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using FizzWare.NBuilder;
// 注意: 使用“重構”菜單上的“重新命名”命令,可以同時更改代碼、服務和設定檔中的類名“Service”。
namespace ProductsServiceLibrary
{
    [DataContract]
    public class ProductData
    {
        [DataMember]
        public string Name;
        [DataMember]
        public string ProductNumber;
        [DataMember]
        public string Color;
        [DataMember]
        public decimal ListPrice;
    }

    public class ProductsServiceImpl : IProductsService
    {
        static IList<tblProduct> ps = Builder<tblProduct>.CreateListOfSize(50).Build();
        static IList<tblProductInventory> pis = Builder<tblProductInventory>.CreateListOfSize(50).Build();

        public List<string> ListProducts()
        {
            var p = ps.Select(item => item.ProductNumber).ToList();

            return p;
        }

        public ProductData GetProduct(string productNumber)
        {
          
            ProductData productData = null;
            tblProduct matchingProduct = ps.First(item => string.Compare(item.ProductNumber, productNumber) == 0);

            productData = new ProductData()
            {
                Name = matchingProduct.Name,
                ProductNumber = matchingProduct.ProductNumber,
                Color = matchingProduct.Color,
                ListPrice = matchingProduct.ListPrice
            };

            return productData;
        }

        public int CurrentStockLevel(string productNumber)
        {
            int stockLevel = 0;
          
          

         
            // Calculate the sum of all quantities for the specified product
            stockLevel = (from pi in pis
                          join p in ps
                          on pi.ProductID equals p.ProductID
                          where String.Compare(p.ProductNumber, productNumber) == 0
                          select (int)pi.Quantity).Sum();

            return stockLevel;
        }

        public bool ChangeStockLevel(string productNumber, short newStockLevel, string shelf, int bin)
        {
            //var pr = Builder<tblProduct>.CreateListOfSize(50).Build();
            //var pri = Builder<tblProductInventory>.CreateListOfSize(50).Build();
            int productID = (from p in ps
                             where String.Compare(p.ProductNumber, productNumber) == 0
                             select p.ProductID).First();
            // Find the ProductInventory object that matches the parameters passed
            // in to the operation
            tblProductInventory productInventory = pis.First(
                            pi => String.Compare(pi.Shelf, shelf) == 0 &&
                            pi.Bin == bin && pi.ProductID == productID);
            // Update the stock level for the ProductInventory object
            productInventory.Quantity += newStockLevel;
            // Save the change back to the database

            return true;
        }
    }
}

 

2、建立WPF應用程式項目ProductsServiceHost,添加對ProductsServiceLibrary類庫引用

MainWindow前台:

 <Grid>
        <Button Height="23" HorizontalAlignment="Left" Margin="51,60,0,0" Name="start" VerticalAlignment="Top" Width="75" Click="start_Click">Start</Button>
        <Button Height="23" HorizontalAlignment="Right" Margin="0,60,56,0" Name="stop" VerticalAlignment="Top" Width="75" IsEnabled="False" Click="stop_Click">Stop</Button>
        <Label Height="23" HorizontalAlignment="Left" Margin="43,0,0,111" Name="label1" VerticalAlignment="Bottom" Width="88">Service Status:</Label>
        <TextBox IsReadOnly="True" Margin="133,0,59,107" Name="status" Text="Service Stopped" Height="26" VerticalAlignment="Bottom"></TextBox>
    </Grid>

 

MainWindow後台:

ServiceHost productsServiceHost = null;
        private void start_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                productsServiceHost = new ServiceHost(typeof(ProductsServiceImpl));
                productsServiceHost.Open();
                stop.IsEnabled = true;
                start.IsEnabled = false;
                status.Text = "Service Running";
            }
            catch (Exception ex)
            {
                handleException(ex);
            }
        }

        private void handleException(Exception ex)
        {
            MessageBox.Show(ex.Message);
        }

        private void stop_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                productsServiceHost.Close();
                stop.IsEnabled = false;
                start.IsEnabled = true;
                status.Text = "Service Stopped";
            }
            catch (Exception ex)
            {
                handleException(ex);
            }

        }

3、app.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
      <services>
        <service name="ProductsServiceLibrary.ProductsServiceImpl">

          <endpoint address="net.tcp://localhost:8080/TcpService"
          binding="netTcpBinding"
          bindingConfiguration="" name="NetTcpBinding_IProductsService"
          contract="ProductsServiceLibrary.IProductsService" />

          <endpoint address="http://localhost:8000/ProductsService/Service.svc"
          binding="basicHttpBinding" name="BasicHttpBinding_IProductsService"
          contract="ProductsServiceLibrary.IProductsService" />

        </service>
      </services>
      <behaviors>
 
      </behaviors>
    </system.serviceModel>
</configuration>

 

注意這裡面設定了兩個endpoint,系統會對這兩個地址啟動wcf服務。用戶端選擇任何一個地址引入service都可以

<client>
   <endpoint address="net.tcp://localhost:8080/TcpService"
                binding="netTcpBinding" contract="ProductsService.IProductsService"
                name="NetTcpBinding_IProductsService" />

          <endpoint address="http://localhost:8000/ProductsService/Service.svc"
                binding="basicHttpBinding"
                bindingConfiguration="BasicHttpBinding_IProductsService"
                contract="ProductsService.IProductsService"
                name="BasicHttpBinding_IProductsService" />

</client>

 

至於windows服務作為宿主

1、建立windows服務項目WindowsProductsService,添加ProductsServiceLibrary類庫引用,將Service1.cs重新命名ServiceHostController.cs

public partial class ServiceHostController : ServiceBase
    {
        private ServiceHost productsServiceHost;
        public ServiceHostController()
        {
            InitializeComponent();
            // The name of the service that appears in the Registry
            this.ServiceName = "ProductsService";
            // Allow an administrator to stop (and restart) the service
            this.CanStop = true;
            // Report Start and Stop events to the Windows event log
            this.AutoLog = true;
        }

        protected override void OnStart(string[] args)
        {
            productsServiceHost = new ServiceHost(typeof(ProductsServiceImpl));
            NetNamedPipeBinding binding = new NetNamedPipeBinding();
            productsServiceHost.AddServiceEndpoint(typeof(IProductsService),
            binding, "net.pipe://localhost/ProductsServicePipe");
            productsServiceHost.Open();
        }

        protected override void OnStop()
        {
            productsServiceHost.Close();
        }

 

2、在ServiceHostController.cs[設計],右鍵添加安裝。點擊serviceInstaller1,修改其屬性ServiceName為ServiceHostController;點擊serviceProcessInstaller1,修改Account

為LocalSystem。產生項目。

3、用管理員權限開啟Visual Studio 命令提示。切到WindowsProductsService項目Debug檔案夾下,運行installutil WindowsProductsService.exe。windows服務則安裝完成

4、在前面的ProductsClient用戶端設定檔中添加一個endpoint

        <endpoint address="net.pipe://localhost/ProductsServicePipe"
              binding="netNamedPipeBinding"
              contract="ProductsService.IProductsService"
              name="NetNamedPipeBinding_IProductsService" />

ok,這樣就大功告成了。欣慰一下吧。

 

小提示:如果你想卸載windows服務,可以運行installutil /u WindowsProductsService.exe

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.