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

WCF 整合 Enterprise Library Policy Injection 實戰

     編輯:關於.NET

背景:為何需要 Policy Injection?

Enterprise Library Policy Injection Application Block (PIAB) 透過方法攔截 實現 AOP,將快取、授權、交易、稽核、例外處理等橫切關注點封裝為 CallHandler,再以 Attribute 或設定檔套用至目標方法。核心在於必須透過 PolicyInjector.Wrap 建立或包裝物件,攔截器才會生效。因此 WCF 整合 PIAB 的關鍵在於:自訂 InstanceProvider,在建立 Service Instance 時經由 PolicyInjector 包裝。

PolicyInjectionInstanceProvider 實作

namespace Artech.WCFExtensions
{
    public class PolicyInjectionInstanceProvider : IInstanceProvider
    {
        private readonly Type _serviceContractType;
        private readonly string _policyInjectorName;

        public PolicyInjectionInstanceProvider(Type serviceContractType, string policyInjectorName)
        {
            _serviceContractType = serviceContractType;
            _policyInjectorName = policyInjectorName;
        }

        public object GetInstance(InstanceContext instanceContext, Message message)
        {
            PolicyInjector policyInjector = string.IsNullOrEmpty(_policyInjectorName)
                ? new PolicyInjectorFactory().Create()
                : new PolicyInjectorFactory().Create(_policyInjectorName);

            Type serviceType = instanceContext.Host.Description.ServiceType;
            object serviceInstance = Activator.CreateInstance(serviceType);

            // RemotingPolicyInjector 需要目標型別實作介面或繼承 MarshalByRefObject
            if (!_serviceContractType.IsInterface && !serviceType.IsMarshalByRef && policyInjector is RemotingPolicyInjector)
                return serviceInstance;

            return policyInjector.Wrap(serviceInstance, _serviceContractType);
        }

        public object GetInstance(InstanceContext instanceContext) => GetInstance(instanceContext, null);

        public void ReleaseInstance(InstanceContext instanceContext, object instance)
        {
            (instance as IDisposable)?.Dispose();
        }
    }
}

兩種 Behavior 套用方式

1. Contract Behavior (Attribute 方式)

[AttributeUsage(AttributeTargets.Interface)]
public class PolicyInjectionBehaviorAttribute : Attribute, IContractBehavior
{
    public string PolicyInjectorName { get; set; }

    public void ApplyDispatchBehavior(ContractDescription contractDescription,
        ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
    {
        dispatchRuntime.InstanceProvider = new PolicyInjectionInstanceProvider(
            contractDescription.ContractType, PolicyInjectorName);
    }
    // 其他介面成員略...
}

套用:[PolicyInjectionBehavior] 標註於 Service Contract 介面。

2. Endpoint Behavior (設定檔方式)


public class PolicyInjectionBehavior : IEndpointBehavior
{
    private readonly string _policyInjectorName;
    public PolicyInjectionBehavior(string policyInjectorName) => _policyInjectorName = policyInjectorName;

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    {
        endpointDispatcher.DispatchRuntime.InstanceProvider = new PolicyInjectionInstanceProvider(
            endpoint.Contract.ContractType, _policyInjectorName);
    }
    // 其他介面成員略...
}

public class PolicyInjectionBehaviorElement : BehaviorExtensionElement
{
    [ConfigurationProperty("policyInjectorName", DefaultValue = "")]
    public string PolicyInjectorName { get => (string)this["policyInjectorName"]; set => this["policyInjectorName"] = value; }
    public override Type BehaviorType => typeof(PolicyInjectionBehavior);
    protected override object CreateBehavior() => new PolicyInjectionBehavior(PolicyInjectorName);
}

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

實戰驗證:TimeService + CachingCallHandler

  • Contract:ITime 含 GetCurrentTime(),標註 [PolicyInjectionBehavior]。
  • Service:TimeService 實作 GetCurrentTime 掛上 [CachingCallHandler],回傳 DateTime.Now。
  • Client:迴圈呼叫 10 次,間隔 1 秒。

結果驗證

  • 啟用 PIAB:10 次回傳相同時間,證明快取生效 (第一次執行後結果被快取,後續直接取快取)。
  • 停用 PIAB:每次回傳不同時間,即時反映當下時間。

Endpoint Behavior 方式同樣驗證成功,證明兩種擴展途徑皆可行。

總結

透過自訂 IInstanceProvider 結合 PolicyInjector.Wrap,無縫將 PIAB 的 AOP 能力引入 WCF 服務實例化管線,支援 Attribute 與設定檔雙重套用模式,為服務層引入快取、授權、記錄等橫切關注點提供標準化解決方案。

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