首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

WCF 實戰:面向介面程式設計與契約優先開發完整演練

     編輯:關於.NET

Windows Communication Foundation (WCF) 的核心哲學是「契約優先、介面導向」。與傳統 ASMX Web Service 或 .NET Remoting 不同,WCF 強制將服務契約(介面)與實作分離,並透過標準化的訊息交換實現真正的跨平台、跨傳輸協定互通。本文以逐步建置專案的方式,完整示範從定義契約、實作服務、自我宿主、建立客戶端代理,到共用複雜資料型別(Model)的端到端開發流程。

專案架構規劃(四個組件)

專案名稱類型職責關鍵參考
ContractsClass Library定義服務契約介面 [ServiceContract]、資料契約 [DataContract]System.ServiceModel
ServicesClass Library實作服務契約介面Contracts, System.ServiceModel
HostConsole Application服務宿主,啟動 ServiceHostContracts, Services, System.ServiceModel
ClientConsole Application消費服務,建立 ChannelFactory/ClientBase 代理Contracts, System.ServiceModel

建立解決方案與 Contracts 專案

新增介面項目

步驟 1:定義服務契約介面

加入 System.ServiceModel 參考

編寫 IHelloContract 介面

// Contracts/IHelloContract.cs
using System.ServiceModel;

namespace Contracts
{
    [ServiceContract]
    public interface IHelloContract
    {
        [OperationContract]
        string HelloWorld();
    }
}

步驟 2:實作服務類別

建立 Services 專案

加入 Contracts 參考

加入 System.ServiceModel 參考

實作 HelloService 類別

// Services/HelloService.cs
using Contracts;
using System.ServiceModel;

namespace Services
{
    public class HelloService : IHelloContract
    {
        public string HelloWorld()
        {
            return "Hello from WCF Service!";
        }
    }
}

步驟 3:建立自我宿主程式

建立 Host 專案

Host 專案加入參考

Host 專案加入 Services 參考

編寫宿主程式碼

// Host/Program.cs
using Services;
using Contracts;
using System.ServiceModel;

namespace Host
{
    class Program
    {
        static void Main(string[] args)
        {
            // 完全以程式碼配置(亦可用 app.config)
            var binding = new NetTcpBinding();
            var address = new EndpointAddress("net.tcp://localhost:81/HelloService");

            using (var host = new ServiceHost(typeof(HelloService), new Uri[] { }))
            {
                host.AddServiceEndpoint(typeof(IHelloContract), binding, address);
                host.Open();
                Console.WriteLine("服務已啟動,按 Enter 結束...");
                Console.ReadLine();
            }
        }
    }
}

步驟 4:建立客戶端程式與手工代理

建立 Client 專案

Client 加入 Contracts 參考

Client 加入 System.ServiceModel

編寫客戶端代理類別

// Client/HelloServiceClient.cs
using Contracts;
using System.ServiceModel;

namespace Client
{
    // 繼承 ClientBase<TChannel> 並實作契約介面,即為型別安全的客戶端代理
    public class HelloServiceClient : ClientBase<IHelloContract>, IHelloContract
    {
        public HelloServiceClient(Binding binding, EndpointAddress address)
            : base(binding, address) { }

        public string HelloWorld()
        {
            return Channel.HelloWorld(); // 委派給內部 Channel
        }
    }
}

步驟 5:客戶端呼叫與除錯驗證

啟動 Host 專案

啟動 Client 專案

Client 成功呼叫服務輸出結果

// Client/Program.cs
using System;
using System.ServiceModel;
using Contracts;

namespace Client
{
    class Program
    {
        static void Main(string[] args)
        {
            var binding = new NetTcpBinding();
            var address = new EndpointAddress("net.tcp://localhost:81/HelloService");
            var proxy = new HelloServiceClient(binding, address);

            Console.WriteLine(proxy.HelloWorld()); // 輸出: Hello from WCF Service!
            Console.ReadLine();
        }
    }
}

進階:共用複雜資料型別 - Model 組件

WCF 最大優勢之一:複雜型別可在服務端與客戶端共用同一組件,避免 Web Service 時代「Proxy 生成的型別與原始型別不同」的問題。

建立 Model 專案

Model 定義 Employee 資料契約

Employee 類別完整定義

// Model/Employee.cs
using System.Runtime.Serialization;

namespace Model
{
    [DataContract]
    public class Employee
    {
        [DataMember] public int ID { get; set; }
        [DataMember] public string Name { get; set; }
        [DataMember] public string Department { get; set; }

        public override string ToString() => $"ID:{ID}, Name:{Name}, Dept:{Department}";
    }
}

擴展契約與實作

修改介面新增 GetEmployee 操作

介面新增 OperationContract

// Contracts/IHelloContract.cs (修改後)
[ServiceContract]
public interface IHelloContract
{
    [OperationContract] string HelloWorld();
    [OperationContract] Employee GetEmployee(); // 新增
}

修改服務實作

實作 GetEmployee 方法

// Services/HelloService.cs (修改後)
public class HelloService : IHelloContract
{
    public string HelloWorld() => "Hello from WCF Service!";

    public Employee GetEmployee()
    {
        return new Employee { ID = 1001, Name = "Terry", Department = "RD" };
    }
}

宿主與客戶端同步更新

Host 專案加入 Model 參考

// Client/HelloServiceClient.cs (修改代理)
public class HelloServiceClient : ClientBase<IHelloContract>, IHelloContract
{
    public HelloServiceClient(Binding binding, EndpointAddress address)
        : base(binding, address) { }

    public string HelloWorld() => Channel.HelloWorld();

    public Employee GetEmployee() => Channel.GetEmployee(); // 直接回傳共用 Model.Employee
}
// Client/Program.cs (呼叫新操作)
static void Main(string[] args)
{
    var binding = new NetTcpBinding();
    var address = new EndpointAddress("net.tcp://localhost:81/HelloService");
    var proxy = new HelloServiceClient(binding, address);

    Console.WriteLine(proxy.HelloWorld());
    var emp = proxy.GetEmployee();
    Console.WriteLine(emp); // 輸出: ID:1001, Name:Terry, Dept:RD
    Console.ReadLine();
}

Client 成功取得共用 Model 物件

核心概念總結

概念說明關鍵屬性/基類
服務契約定義服務暴露的操作[ServiceContract], [OperationContract]
資料契約定義跨邊界傳遞的資料結構[DataContract], [DataMember]
端點Address + Binding + ContractEndpointAddress, Binding, Contract
客戶端代理型別安全的呼叫包裝器繼承 ClientBase<T> 並實作 T
型別共用服務/客戶端引用同一 Model 組件無需產生 Proxy,直接使用原始型別

實務建議

  • **契約組件獨立部署**:Contracts 與 Model 可打包為 NuGet 套件,服務端與客戶端分別引用,實現真正的契約優先治理。
  • **生產環境改用組態檔**:Binding、Address、Behavior 等移至 app.config/web.config,利用 ConfigurationChannelFactory 動態載入,避免重新編譯。
  • **考慮非同步模式**:.NET 4.5+ 建議使用 Task<T> 非同步操作契約,搭配 ChannelFactory<T> 建立非同步代理。
  • **錯誤處理**:實作 IErrorHandler 統一將例外轉為 FaultException<TDetail> 回傳,避免通道進入 Faulted 狀態。

透過契約優先、介面導向、型別共用,WCF 讓分散式系統開發回歸強型別、編譯期檢查的軌道,是企業級整合的堅實基石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved