z4kn4fein / stashbox

A lightweight, fast, and portable dependency injection framework for .NET-based solutions.
https://z4kn4fein.github.io/stashbox
MIT License
140 stars 10 forks source link

Question: Please explain Interception example a bit more. #110

Closed schuettecarsten closed 2 years ago

schuettecarsten commented 2 years ago

Please explain Interception example a bit more. I have no idea why the sample works. https://z4kn4fein.github.io/stashbox/#/advanced/decorators?id=interception

z4kn4fein commented 2 years ago

Hi,

Thank you for reaching out! You are right, the interception example is not detailed enough, I'll put there a better explanation.

But, let me summarize here quick how interception works with Castle DynamicProxy and Stashbox:

With Castle's DefaultProxyBuilder you can generate proxy implementation classes for interfaces. These proxy classes depend on the actual implementation of the given interface and an IInterceptor collection that holds the additional logic you want to be executed on each call of the interface's methods.

A simplified example:

Here's an interface that we want to extend with additional logic.

interface IExample
{
    void DoWork();
}

We can generate a proxy implementation type with DefaultProxyBuilder:

Type exampleProxyType = proxyBuilder.CreateInterfaceProxyTypeWithTargetInterface(
    typeof(IExample), // the interface the proxy must be generated from
    new Type[0], 
    ProxyGenerationOptions.Default);

The generated proxy type will look something like this:

class generated_ProxyIExample : IExample 
{
    public generated_ProxyIExample(IExample actualImplementation, IInterceptor[] interceptors)
    { /* ... */ }

    public void DoWork()
    {
        // it's calling the interceptors and the actualImplementation's DoWork() 
    }
}

Within the IInterceptor implementations, you can define the additional logic you want to get executed on the interface's method calls.

class ExampleInterceptor : IInterceptor
{ 
    public void Intercept(IInvocation invocation)
    {
        Console.WriteLine($"Before method {invocation.GetConcreteMethod().Name}");
        invocation.Proceed();
        Console.WriteLine($"After method {invocation.GetConcreteMethod().Name}");
     }
}

You can wire all this together, so Stashbox can automatically apply the interceptors to your interfaces.

// register your actual IExample implementation.
container.Register<IExample, ActualExampleImplementation>(); 

// register your interceptor so Stashbox can inject it into your proxy class,
// as the proxy class depend on an IInterceptor collection, you can register more than one interceptor of course.
container.Register<IInterceptor, ExampleInterceptor>();

// register the proxy class as a decorator, so Stashbox can resolve the proxy class 
// when IExample is requested and can inject your actual implementation into it.
container.RegisterDecorator<IExample>(exampleProxyType);

When we resolve IExample from Stashbox the following will happen:

// container.Resolve<IExample>() will translates to:
IExample result = new generated_ProxyIExample(
    new ActualExampleImplementation(), 
    new IInterceptor[] { new ExampleInterceptor() }
);

This is it basically, let me know if you need more details.

github-actions[bot] commented 2 years ago

This issue is marked stale because it has been open for 90 days with no activity.

github-actions[bot] commented 2 years ago

This issue was closed due to no activity.