DEV Community

loading...

Implement Chain of Responsibility/Commands in C# Using ChainRunner

Mohammad Shafie-Zadeh
Updated on ・2 min read

I have been working on an ASP.NET Core Web API application which is responsible for users' comments. The application receives new comments and based on multiple business criteria decides to whether reject or censor them. In nutshell, each new comment must go through the following steps:

  • Censor curse words
  • Modify incorrect words
  • Reject if it has improper tone

The steps are not that complex and must be executed sequentially. To implement these steps, I decided to go for chain of responsibility pattern. However, I could not find a simple and proper library to implement this pattern so I created a library called ChainRunner to make all this work.

ChainRunner Flow Diagram

The picture depicts how ChainRunner works

Implementation

Below you can seee how I used ChainRunner to implement the steps. For each step I created a responsibility handler:

public class CensorCurseWordsHandler : IResponsibilityHandler<Comment>
{
    public Task HandleAsync(Comment request, CancellationToken cancellationToken = default)
    {
        // process comment ...
    }
}

public class ModifyIncorrectWordsHandler : IResponsibilityHandler<Comment>
{
    public Task HandleAsync(Comment request, CancellationToken cancellationToken = default)
    {
        // process comment ...
    }
}

public class ImproperToneHandler : IResponsibilityHandler<Comment>
{
    public Task HandleAsync(Comment request, CancellationToken cancellationToken = default)
    {
        // process comment ...
    }
}

Enter fullscreen mode Exit fullscreen mode

Then, I configured the chain in Startup.cs (ASP.NET Core):

services.AddChain<Comment>()
        .WithHandler<CensorCurseWordsHandler>()
        .WithHandler<ModifyIncorrectWordsHandler>()
        .WithHandler<ImproperToneHandler>();
Enter fullscreen mode Exit fullscreen mode

Finally, I injected the chain into my class and ran the chain like so:


[ApiController]
[Route("[controller]")]
public class CommentController
{
    private readonly IChain<Comment> _chain;

    public CommentController(IChain<Comment> chain)
    {
        _chain = chain;
    }

    [HttpPost]
    public async Task<IActionResult> Post(Comment comment)
    {
        await _chain.RunAsync(comment);

        return Ok();
    }
}
Enter fullscreen mode Exit fullscreen mode

Links

Discussion (1)

Collapse
alwaysmaap profile image
Mohammad ali Ali panah

Thanks that exacly what I was looking for <333