攔截器不必每次都呼叫 Proceed

攔截器是實現日誌記錄或身份驗證等跨領域問題的好工具。假設我們有以下服務:

public interface IService
{
    string CreateOrder(NetworkCredential credentials, Order orderToCreate);
    string DeleteOrder(NetworkCredential credentials, int orderId);
}

public class Service : IService
{
    public string CreateOrder(NetworkCredential credentials, Order orderToCreate)
    {
        // ...

        return "Order was created succesfully.";
    }

    public string DeleteOrder(NetworkCredential credentials, int orderId)
    {
        // ...

        return "Order was deleted succesfully.";
    }
}

我們可以建立以下攔截器:

public class AuthorizationInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        var userCredentials = invocation.Arguments[0] as NetworkCredential;
        
        if (userCredentials.UserName == "tom" && userCredentials.Password == "pass123")
            // this ^ verification is obviously silly, never do real security like this
        {
            invocation.Proceed();
        }
        else
        {
            invocation.ReturnValue = $"User '{userCredentials.UserName}' was not authenticated.";
        }
    }
}

這可以像這樣註冊和使用:

var container = new WindsorContainer();
container.Register(
    Component.For<AuthorizationInterceptor>(),
    Component.For<IService>().ImplementedBy<Service>().Interceptors<AuthorizationInterceptor>());

var service = container.Resolve<IService>();

System.Diagnostics.Debug.Assert(
    service.DeleteOrder(new NetworkCredential { UserName = "paul", Password = "pass321" }, 8)
        == "User 'paul' was not authenticated.");

System.Diagnostics.Debug.Assert(
    service.CreateOrder(new NetworkCredential { UserName = "tom", Password = "pass123" }, new Order())
        == "Order was created succesfully.");

重要的一課是攔截器可以決定傳遞呼叫,如果沒有,它可以使用 ReturnValue 屬性提供任意返回值。