Home > database >  How to execute a default method before the interface implementation code C#?
How to execute a default method before the interface implementation code C#?

Time:04-27

I have an interface which implements only one method:

public interface IHandler<T> where T : Comand
{
    Task<IResultComand> HandlerAsync(T comand);
}

And I use it in my classes as follows:

public class ProductHandler : IHandler<NewProductComand>,
                              IHandler<EditProductComand>,
                              IHandler<DeleteProductComand>

public async Task<IResultComand> HandlerAsync(NewProductComand comand) 
{
        ResultComand result = new();

        comand.Validate();
        if (!comand.Valid)
        {
            return result;
        }

        //Create new product

        return result;
}

public async Task<IResultComand> HandlerAsync(EditProductComand comand) 
{
        ResultComand result = new();

        comand.Validate();
        if (!comand.Valid)
        {
            return result;
        }

        //Edit product

        return result;
}

public async Task<IResultComand> HandlerAsync(DeleteProductComand comand) 
{
        ResultComand result = new();

        comand.Validate();
        if (!comand.Valid)
        {
            return result;
        }

        //Delete product

        return result;
}

And my Comand has the following code:

 public abstract class Comand
 {
    public bool Valid { get; set; }

    public abstract void Validate();
 }

How to make the following code run implicitly before executing the implementation code in HandlerAsync? (Some thing like a ActionFilter Web API .NET)

    ResultComand result = new();

    comand.Validate();
    if (!comand.Valid)
    {
        return result;
    }

CodePudding user response:

You're looking for the Decorator Pattern.

Basically, you leave your 'base' CommandHandler as it is and let it do its job, but you add an additional class that implements the same interface:

ExtraStuffCommandHandlerDecorator<TComand> : IHandler<TComand>
    where TComand : Comand
{
    readonly IHandler<TComand> _decorated;

    public ExtraStuffCommandHandlerDecorator(IHandler<TComand> decorated)
    {
        _decorated = decorated;
    }

    public async Task<IResultComand> HandlerAsync(TComand comand)
    {
        // Do stuff before base command execution

        IResultComand result = await _decorated.HandlerAsync(comand);

        // Do stuff after base command execution

        return result;
    }
}

Now your mediator that is currently instantiating and calling the base handler directly, should instead look up the decorator and call that instead, passing the base handler in as a constructor argument.

Using decorators is well supported by Autofac's RegisterGenericDecorator method. Implementation with Asp Core DI is a little more complex, but here's a guide.

https://andrewlock.net/adding-decorated-classes-to-the-asp.net-core-di-container-using-scrutor/#manually-creating-decorators-with-the-asp-net-core-di-container

  • Related