Table of Contents

Class Proxy<TIn, TOut>.Builder

Namespace
PatternKit.Structural.Proxy
Assembly
PatternKit.Core.dll

Fluent builder for Proxy<TIn, TOut>.

public sealed class Proxy<TIn, TOut>.Builder
Inheritance
Proxy<TIn, TOut>.Builder
Inherited Members
Extension Methods

Remarks

The builder supports various proxy patterns:

Builders are mutable and not thread-safe. Each call to Build() creates an immutable proxy instance.

Methods

After(Action<TIn, TOut>)

Adds an action to execute after the subject returns.

public Proxy<TIn, TOut>.Builder After(Action<TIn, TOut> action)

Parameters

action Action<TIn, TOut>

Action to execute with input and output.

Returns

Proxy<TIn, TOut>.Builder

This builder for chaining.

Examples

var proxy = Proxy<int, int>.Create(x => x * 2)
    .After((input, result) => Console.WriteLine($"{input} -> {result}"))
    .Build();

Remarks

Useful for side effects like logging results, notifications, or post-processing that doesn't modify the result.

Before(Action<TIn>)

Adds an action to execute before delegating to the subject.

public Proxy<TIn, TOut>.Builder Before(Action<TIn> action)

Parameters

action Action<TIn>

Action to execute with the input.

Returns

Proxy<TIn, TOut>.Builder

This builder for chaining.

Examples

var proxy = Proxy<string, int>.Create(s => s.Length)
    .Before(s => Console.WriteLine($"Processing: {s}"))
    .Build();

Remarks

Useful for side effects like logging, validation, or notifications that don't affect the result.

Build()

Builds an immutable Proxy<TIn, TOut> with the configured behavior.

public Proxy<TIn, TOut> Build()

Returns

Proxy<TIn, TOut>

A new Proxy<TIn, TOut> instance.

Exceptions

InvalidOperationException

Thrown when the configuration is invalid.

CachingProxy()

Configures a caching proxy that memoizes results to avoid redundant subject invocations.

public Proxy<TIn, TOut>.Builder CachingProxy()

Returns

Proxy<TIn, TOut>.Builder

This builder for chaining.

Examples

var proxy = Proxy<int, int>.Create(x => ExpensiveCalculation(x))
    .CachingProxy()
    .Build();
var r1 = proxy.Execute(5); // Calls subject
var r2 = proxy.Execute(5); // Returns cached result

Remarks

Caching Proxy Pattern: Stores results in a dictionary keyed by input. Subsequent calls with the same input return the cached result without invoking the subject.

Note: This requires to have proper equality semantics. For reference types, consider implementing IEquatable<T> or providing a custom comparer.

CachingProxy(IEqualityComparer<TIn>)

Configures a caching proxy with a custom equality comparer.

public Proxy<TIn, TOut>.Builder CachingProxy(IEqualityComparer<TIn> comparer)

Parameters

comparer IEqualityComparer<TIn>

The equality comparer for cache keys.

Returns

Proxy<TIn, TOut>.Builder

This builder for chaining.

Examples

var proxy = Proxy<string, int>.Create(s => s.Length)
    .CachingProxy(StringComparer.OrdinalIgnoreCase)
    .Build();

Intercept(Interceptor)

Adds a custom interceptor that has full control over subject invocation.

public Proxy<TIn, TOut>.Builder Intercept(Proxy<TIn, TOut>.Interceptor interceptor)

Parameters

interceptor Proxy<TIn, TOut>.Interceptor

The interceptor delegate.

Returns

Proxy<TIn, TOut>.Builder

This builder for chaining.

Examples

var proxy = Proxy<int, int>.Create(x => x * 2)
    .Intercept((in int x, next) => {
        if (x < 0) return 0; // Short-circuit negative inputs
        return next(in x);
    })
    .Build();

Remarks

The interceptor receives the input and a delegate to the subject (or next layer). It can:

  • Modify the input before calling the subject
  • Skip calling the subject entirely (short-circuit)
  • Modify the output before returning
  • Add cross-cutting concerns (logging, timing, error handling)

LoggingProxy(Action<string>)

Configures a logging proxy that logs method invocations and results.

public Proxy<TIn, TOut>.Builder LoggingProxy(Action<string> logger)

Parameters

logger Action<string>

Action to invoke for logging (receives log messages).

Returns

Proxy<TIn, TOut>.Builder

This builder for chaining.

Examples

var proxy = Proxy<int, int>.Create(x => x * 2)
    .LoggingProxy(Console.WriteLine)
    .Build();

Remarks

Logging Proxy Pattern: Intercepts calls to log input and output for debugging or auditing. The logger is invoked before and after the subject execution.

ProtectionProxy(AccessValidator)

Configures a protection proxy that validates access before delegating to the subject.

public Proxy<TIn, TOut>.Builder ProtectionProxy(Proxy<TIn, TOut>.AccessValidator validator)

Parameters

validator Proxy<TIn, TOut>.AccessValidator

Function that returns true if access is allowed.

Returns

Proxy<TIn, TOut>.Builder

This builder for chaining.

Examples

var proxy = Proxy<User, bool>.Create(user => DeleteUser(user))
    .ProtectionProxy(user => user.IsAdmin)
    .Build();

Remarks

Protection Proxy Pattern: Controls access to the subject based on validation logic. If the validator returns false, an UnauthorizedAccessException is thrown.

VirtualProxy(SubjectFactory)

Configures a virtual proxy that lazily initializes the subject on first access.

public Proxy<TIn, TOut>.Builder VirtualProxy(Proxy<TIn, TOut>.SubjectFactory factory)

Parameters

factory Proxy<TIn, TOut>.SubjectFactory

Factory function that creates the real subject.

Returns

Proxy<TIn, TOut>.Builder

This builder for chaining.

Examples

var proxy = Proxy<string, Database>.Create()
    .VirtualProxy(() => new Database("connection-string"))
    .Build();
// Database is not created until first Execute call

Remarks

Virtual Proxy Pattern: Delays expensive object creation until the object is actually needed. The factory is invoked only once, on the first call to Execute(in TIn), and the result is cached. Thread-safe initialization is guaranteed.