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

WCF CallContextInitializer 實戰:優雅實現多語系本地化

     編輯:關於.NET

問題背景:Culture 資訊不應污染 Service Contract

多語系服務常見做法是將 Culture 當作參數傳遞,但 Culture 屬於基礎設施關注點,非業務邏輯一部分。理想模式:Client 自動將當前 Culture 放入 SOAP Header,Server 透過擴展點攔截、設定執行緒 Culture,服務邏輯僅專注「依據當前執行緒 Culture 取得資源」。

CallContextInitializer 介入點

ICallContextInitializer 提供 BeforeInvoke (設定 Context) 與 AfterInvoke (清理 Context) 兩個切點,完美契合「臨時切換 Culture」需求。

CultureSettingCallContextInitializer 實作


public class CultureSettingCallContextInitializer : ICallContextInitializer
{
    private const string CultureHeaderName = "__CultureInfo";
    private const string CultureHeaderNs = "urn:artech.com";

    public object BeforeInvoke(InstanceContext instanceContext, IClientChannel channel, Message message)
    {
        var saved = new[] { Thread.CurrentThread.CurrentCulture, Thread.CurrentThread.CurrentUICulture };
        if (message.Headers.FindHeader(CultureHeaderName, CultureHeaderNs) > -1)
        {
            var culture = message.Headers.GetHeader<CultureInfo>(CultureHeaderName, CultureHeaderNs);
            Thread.CurrentThread.CurrentCulture = culture;
            Thread.CurrentThread.CurrentUICulture = culture;
        }
        return saved; // 傳遞給 AfterInvoke
    }

    public void AfterInvoke(object correlationState)
    {
        var cultures = correlationState as CultureInfo[];
        if (cultures != null)
        {
            Thread.CurrentThread.CurrentCulture = cultures[0];
            Thread.CurrentThread.CurrentUICulture = cultures[1];
        }
    }
}

兩種 Behavior 套用方式

1. OperationBehavior (Attribute 針對單一作業)


public class CultureSettingBehaviorAttribute : Attribute, IOperationBehavior
{
    public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
        => dispatchOperation.CallContextInitializers.Add(new CultureSettingCallContextInitializer());
    // 其他介面成員空實作...
}

套用:[CultureSettingBehavior] 標註於 Contract 作業或 Service 實作方法。

2. EndpointBehavior (設定檔套用至端點所有作業)


public class CultureSettingBehavior : IEndpointBehavior
{
    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    {
        foreach (var op in endpointDispatcher.DispatchRuntime.Operations)
            op.CallContextInitializers.Add(new CultureSettingCallContextInitializer());
    }
    // 其他介面成員空實作...
}

public class CultureSettingBehaviorElement : BehaviorExtensionElement
{
    public override Type BehaviorType => typeof(CultureSettingBehavior);
    protected override object CreateBehavior() => new CultureSettingBehavior();
}

設定檔註冊 behaviorExtensions,於 endpointBehaviors 參考 cultureSettingElement。

Client 端手動注入 Header (示範用)


using (var scope = new OperationContextScope(proxy as IContextChannel))
{
    var header = new MessageHeader<CultureInfo>(Thread.CurrentThread.CurrentUICulture);
    OperationContext.Current.OutgoingMessageHeaders.Add(header.GetUntypedHeader("__CultureInfo", "urn:artech.com"));
    Console.WriteLine(proxy.GetMessage());
}

實務上可結合上一篇 ClientMessageInspector 自動化此步驟。

驗證結果

  • Client 切換 Culture 為 en-US -> 服務回傳英文訊息。
  • Client 切換 Culture 為 zh-CN -> 服務回傳中文訊息。
  • 服務執行緒 Culture 於呼叫結束自動還原,不影響後續請求。

總結

CallContextInitializer 讓我們在不修改 Service Contract 的前提下,優雅實現基於 SOAP Header 的 Culture 流轉與執行緒切換,展現 WCF 擴展點處理基礎設施關注點的強大能力。

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