<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Luciano Azevedo</title>
    <description>The latest articles on DEV Community by Luciano Azevedo (@oluciaano).</description>
    <link>https://dev.to/oluciaano</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2578506%2F87fc6ae6-24ea-4381-9b8a-c4cc17457c5f.jpg</url>
      <title>DEV Community: Luciano Azevedo</title>
      <link>https://dev.to/oluciaano</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/oluciaano"/>
    <language>en</language>
    <item>
      <title>Your first background job in .NET with NexJob</title>
      <dc:creator>Luciano Azevedo</dc:creator>
      <pubDate>Tue, 13 Oct 2026 12:57:29 +0000</pubDate>
      <link>https://dev.to/oluciaano/your-first-background-job-in-net-with-nexjob-1c17</link>
      <guid>https://dev.to/oluciaano/your-first-background-job-in-net-with-nexjob-1c17</guid>
      <description>&lt;h2&gt;
  
  
  Your first background job in .NET with NexJob
&lt;/h2&gt;

&lt;p&gt;Sooner or later a web app needs to do something that should not block the request: send an e-mail, resize an image, call a slow API. This post builds the smallest possible background job in .NET 8 and runs it. No database, no extra services, about five minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you need
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;a href="https://dotnet.microsoft.com/download" rel="noopener noreferrer"&gt;.NET 8 SDK&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;A terminal&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1. A project
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet new worker &lt;span class="nt"&gt;-n&lt;/span&gt; MyJobs
&lt;span class="nb"&gt;cd &lt;/span&gt;MyJobs
dotnet add package NexJob
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A worker service is the simplest host. Everything below works the same inside an ASP.NET Core app.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Register NexJob
&lt;/h2&gt;

&lt;p&gt;Two lines in &lt;code&gt;Program.cs&lt;/code&gt;: one to add NexJob, one to let it find your job classes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;NexJob&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateDefaultBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ConfigureServices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;services&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddNexJob&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddNexJobJobs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Program&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Assembly&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Call &lt;code&gt;AddNexJob()&lt;/code&gt; once. Calling it twice registers the background services twice.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Write the job
&lt;/h2&gt;

&lt;p&gt;A job is a class with one method. Implement &lt;code&gt;IJob&lt;/code&gt; when the work needs no input.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HelloJob&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IJob&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;ExecuteAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;ct&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Hello at &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;DateTimeOffset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UtcNow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;O&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CompletedTask&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things worth knowing right away:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NexJob builds the job from your dependency injection container, so constructor injection works like anywhere else in .NET.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;CancellationToken&lt;/code&gt; is yours to honor. When the host shuts down, it is how the job finds out.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Enqueue it
&lt;/h2&gt;

&lt;p&gt;Ask the container for &lt;code&gt;IScheduler&lt;/code&gt; and enqueue the job.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StartAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;scheduler&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetRequiredService&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IScheduler&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;scheduler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EnqueueAsync&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;HelloJob&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WaitForShutdownAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Run it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello at 2026-10-13T12:33:27.9831829+00:00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is the whole loop. The job was stored, picked up by a worker running inside your process, and executed. There is no separate worker process to deploy.&lt;/p&gt;

&lt;h2&gt;
  
  
  A job that takes input
&lt;/h2&gt;

&lt;p&gt;Most real jobs need data. Implement &lt;code&gt;IJob&amp;lt;T&amp;gt;&lt;/code&gt; and use a &lt;code&gt;record&lt;/code&gt; for the input: it serializes cleanly and cannot change after it is enqueued.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;SendWelcomeEmailInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;UserName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SendWelcomeEmailJob&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IJob&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;SendWelcomeEmailInput&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IEmailService&lt;/span&gt; &lt;span class="n"&gt;_email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;SendWelcomeEmailJob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IEmailService&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_email&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;ExecuteAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SendWelcomeEmailInput&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;ct&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SendAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;$"Welcome, &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UserName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ct&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;scheduler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EnqueueAsync&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;SendWelcomeEmailJob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SendWelcomeEmailInput&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;SendWelcomeEmailInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"user@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Jane"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What happens if the process stops?
&lt;/h2&gt;

&lt;p&gt;With the default storage, jobs live in memory and are gone when the process exits. That is fine for trying things out and for tests. For anything real, add a database provider:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet add package NexJob.Postgres
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddNexJobPostgres&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Host=localhost;Database=nexjob;Username=postgres;Password=secret"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddNexJob&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Register the provider before &lt;code&gt;AddNexJob()&lt;/code&gt;, so it replaces the in-memory default. SQL Server, Redis and MongoDB providers exist too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to go next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Retries and what happens when a job keeps failing&lt;/li&gt;
&lt;li&gt;Delays, recurring jobs and deadlines&lt;/li&gt;
&lt;li&gt;Seeing what your jobs are doing (the next posts in this series)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Source and samples: &lt;a href="https://github.com/oluciano/NexJob" rel="noopener noreferrer"&gt;https://github.com/oluciano/NexJob&lt;/a&gt;&lt;br&gt;
Documentation: &lt;a href="https://oluciano.github.io/NexJob/" rel="noopener noreferrer"&gt;https://oluciano.github.io/NexJob/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>backgroundjobs</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>🏗️ Aplicando Adapter e Decorator Patterns com Injeção de Dependência no C#</title>
      <dc:creator>Luciano Azevedo</dc:creator>
      <pubDate>Sun, 02 Feb 2025 22:00:25 +0000</pubDate>
      <link>https://dev.to/oluciaano/aplicando-adapter-e-decorator-patterns-com-injecao-de-dependencia-no-c-2cb4</link>
      <guid>https://dev.to/oluciaano/aplicando-adapter-e-decorator-patterns-com-injecao-de-dependencia-no-c-2cb4</guid>
      <description>&lt;p&gt;Ao desenvolver software, muitas vezes precisamos integrar sistemas legados e adicionar funcionalidades sem modificar diretamente o código existente. Para isso, podemos usar padrões de design como Adapter e Decorator, que nos ajudam a estruturar o código de forma modular e reutilizável.&lt;/p&gt;

&lt;p&gt;Neste artigo, vamos explorar como usar esses padrões no C# com injeção de dependência (DI) e a biblioteca Scrutor para simplificar o registro dos decorators.&lt;/p&gt;

&lt;p&gt;🎯 Cenário do Problema&lt;/p&gt;

&lt;p&gt;Imagine que temos um serviço legado que processa pagamentos, mas ele não segue a interface moderna que queremos usar em nosso sistema. Além disso, queremos adicionar logs ao processamento de pagamentos sem modificar diretamente o serviço existente.&lt;/p&gt;

&lt;p&gt;Vamos resolver isso combinando Adapter e Decorator!&lt;/p&gt;

&lt;p&gt;📌 Passo 1: Definindo a Interface Padrão&lt;/p&gt;

&lt;p&gt;Criamos a interface IPaymentProcessor para definir um contrato padrão para processadores de pagamento:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public interface IPaymentProcessor
{
    void ProcessPayment(decimal amount);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essa interface será usada tanto pelo Adapter quanto pelo Decorator.&lt;/p&gt;

&lt;p&gt;📌 Passo 2: Criando o Serviço Legado&lt;/p&gt;

&lt;p&gt;Nosso serviço legado (LegacyPaymentService) não segue a interface moderna. Ele espera um string em vez de um decimal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public sealed class LegacyPaymentService
{
    public void MakePayment(string amount)
    {
        Console.WriteLine($"Processing payment of {amount} via legacy system.");
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para integrá-lo ao sistema moderno, usaremos o Adapter Pattern.&lt;/p&gt;

&lt;p&gt;📌 Passo 3: Criando o Adapter&lt;/p&gt;

&lt;p&gt;O Adapter faz a conversão entre IPaymentProcessor e LegacyPaymentService:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public sealed class PaymentAdapter : IPaymentProcessor
{
    private readonly LegacyPaymentService _legacyPaymentService;

    public PaymentAdapter(LegacyPaymentService legacyPaymentService)
    {
        _legacyPaymentService = legacyPaymentService;
    }

    public void ProcessPayment(decimal amount)
    {
        string amountString = amount.ToString("F2");
        _legacyPaymentService.MakePayment(amountString);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora podemos usar PaymentAdapter em qualquer lugar que espera IPaymentProcessor.&lt;/p&gt;

&lt;p&gt;📌 Passo 4: Criando o Decorator para Logging&lt;/p&gt;

&lt;p&gt;Agora adicionamos um Decorator (LoggingDecorator) para registrar logs sempre que um pagamento for processado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Microsoft.Extensions.Logging;

public class LoggingDecorator : IPaymentProcessor
{
    private readonly IPaymentProcessor _innerProcessor;
    private readonly ILogger&amp;lt;LoggingDecorator&amp;gt; _logger;

    public LoggingDecorator(IPaymentProcessor innerProcessor, ILogger&amp;lt;LoggingDecorator&amp;gt; logger)
    {
        _innerProcessor = innerProcessor;
        _logger = logger;
    }

    public void ProcessPayment(decimal amount)
    {
        _logger.LogInformation($"Iniciando processamento do pagamento de {amount:C}");
        _innerProcessor.ProcessPayment(amount);
        _logger.LogInformation($"Pagamento de {amount:C} processado com sucesso.");
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse Decorator adiciona logs antes e depois da chamada real ao PaymentProcessor, sem modificar sua implementação.&lt;/p&gt;

&lt;p&gt;📌 Passo 5: Criando o Worker Service&lt;/p&gt;

&lt;p&gt;Para simular um sistema em execução contínua, criamos um Worker Service que chama IPaymentProcessor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Threading;
using System.Threading.Tasks;

public class PaymentWorker : BackgroundService
{
    private readonly ILogger&amp;lt;PaymentWorker&amp;gt; _logger;
    private readonly IPaymentProcessor _paymentProcessor;

    public PaymentWorker(ILogger&amp;lt;PaymentWorker&amp;gt; logger, IPaymentProcessor paymentProcessor)
    {
        _logger = logger;
        _paymentProcessor = paymentProcessor;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation("Iniciando ciclo do Worker...");

            _paymentProcessor.ProcessPayment(100.50m); // Simulando pagamento

            await Task.Delay(5000, stoppingToken); // Executa a cada 5 segundos
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;📌 Passo 6: Configurando a Injeção de Dependência (DI) com Scrutor&lt;/p&gt;

&lt;p&gt;Podemos usar a biblioteca Scrutor para simplificar o registro do Decorator.&lt;br&gt;
Primeiro, instalamos a dependência via NuGet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet add package Scrutor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, configuramos os serviços no Program.cs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Scrutor;

class Program
{
    static void Main(string[] args)
    {
        var host = Host.CreateDefaultBuilder(args)
            .ConfigureServices((hostContext, services) =&amp;gt;
            {
                services.AddSingleton&amp;lt;LegacyPaymentService&amp;gt;(); // Serviço legado

                // Registra o Adapter
                services.AddSingleton&amp;lt;PaymentAdapter&amp;gt;(); 
                services.AddSingleton&amp;lt;IPaymentProcessor&amp;gt;(provider =&amp;gt; 
                    provider.GetRequiredService&amp;lt;PaymentAdapter&amp;gt;());

                // Adiciona o LoggingDecorator automaticamente com Scrutor
                services.Decorate&amp;lt;IPaymentProcessor, LoggingDecorator&amp;gt;();

                // Registra o Worker Service
                services.AddHostedService&amp;lt;PaymentWorker&amp;gt;(); 
                services.AddLogging(); 
            })
            .Build();

        host.Run();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;📌 Estrutura de Pastas&lt;/p&gt;

&lt;p&gt;Aqui está a estrutura do projeto para manter tudo organizado:&lt;/p&gt;

&lt;p&gt;📂 PaymentProcessorApp&lt;br&gt;
│── 📂 Adapters&lt;br&gt;
│   └── PaymentAdapter.cs&lt;br&gt;
│── 📂 Decorators&lt;br&gt;
│   └── LoggingDecorator.cs&lt;br&gt;
│── 📂 Interfaces&lt;br&gt;
│   └── IPaymentProcessor.cs&lt;br&gt;
│── 📂 Services&lt;br&gt;
│   └── LegacyPaymentService.cs&lt;br&gt;
│── 📂 Workers&lt;br&gt;
│   └── PaymentWorker.cs&lt;br&gt;
│── Program.cs&lt;br&gt;
│── PaymentProcessorApp.csproj&lt;/p&gt;

&lt;p&gt;🚀 Benefícios dessa Abordagem&lt;/p&gt;

&lt;p&gt;✅ Código modular e reutilizável → Podemos adicionar novos IPaymentProcessor ou decorators sem alterar a implementação principal.&lt;br&gt;
✅ Extensibilidade → Podemos criar mais decorators, como um validador ou auditoria.&lt;br&gt;
✅ Baixo acoplamento → Usando DI e Scrutor, evitamos dependências rígidas.&lt;br&gt;
✅ Facilidade de Testes → Podemos testar LoggingDecorator separadamente.&lt;/p&gt;

&lt;p&gt;Essa abordagem combina Adapter e Decorator Patterns com Injeção de Dependência, mantendo o código limpo, flexível e escalável.&lt;/p&gt;

&lt;p&gt;Se você gostou, deixe um comentário ou compartilhe! 🚀🔥&lt;/p&gt;




</description>
      <category>csharp</category>
      <category>designpatterns</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Adapter Pattern em C# com Injeção de Dependência e Worker Service</title>
      <dc:creator>Luciano Azevedo</dc:creator>
      <pubDate>Sun, 02 Feb 2025 20:36:38 +0000</pubDate>
      <link>https://dev.to/oluciaano/adapter-pattern-em-c-com-injecao-de-dependencia-e-worker-service-4f61</link>
      <guid>https://dev.to/oluciaano/adapter-pattern-em-c-com-injecao-de-dependencia-e-worker-service-4f61</guid>
      <description>&lt;p&gt;🚀 Aplicando o Adapter Pattern em C# com Injeção de Dependência e Worker Service&lt;/p&gt;

&lt;p&gt;📌 Introdução&lt;/p&gt;

&lt;p&gt;Ao trabalhar com sistemas legados, é comum encontrar APIs ou serviços que não seguem as interfaces modernas do nosso código. Em vez de modificar diretamente esses sistemas, podemos usar o Adapter Pattern para fazer a integração de forma elegante.&lt;/p&gt;

&lt;p&gt;Neste artigo, vou mostrar como implementar o Adapter Pattern em C#, usando Injeção de Dependência (DI) e um Worker Service para simular um processo contínuo.&lt;/p&gt;




&lt;p&gt;🎯 O que é o Adapter Pattern?&lt;/p&gt;

&lt;p&gt;O Adapter Pattern é um padrão estrutural que permite que objetos com interfaces incompatíveis trabalhem juntos. Ele age como um intermediário, convertendo a interface de uma classe para outra esperada pelo sistema.&lt;/p&gt;

&lt;p&gt;📌 Quando usar?&lt;/p&gt;

&lt;p&gt;✅ Quando precisamos integrar APIs ou bibliotecas legadas que não podem ser alteradas.&lt;br&gt;
✅ Quando queremos manter um código desacoplado e flexível.&lt;br&gt;
✅ Quando temos diferentes implementações que precisam seguir um mesmo contrato.&lt;/p&gt;



&lt;p&gt;🛠️ Implementação&lt;/p&gt;

&lt;p&gt;Vamos construir um exemplo onde temos um sistema de pagamentos legados e queremos integrá-lo a um Worker Service que processa pagamentos periodicamente.&lt;/p&gt;

&lt;p&gt;🏗️ 1️⃣ Criamos a interface moderna IPaymentProcessor&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public interface IPaymentProcessor
{
    void ProcessPayment(decimal amount);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;🏗️ 2️⃣ Criamos o serviço legado LegacyPaymentService&lt;/p&gt;

&lt;p&gt;Este é um serviço que já existe e que queremos reutilizar, mas ele usa uma interface diferente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public sealed class LegacyPaymentService
{
    public void MakePayment(string amount)
    {
        Console.WriteLine($"Processing payment of {amount} via legacy system.");
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;🏗️ 3️⃣ Criamos o Adapter PaymentAdapter&lt;/p&gt;

&lt;p&gt;Aqui adaptamos LegacyPaymentService para seguir a interface IPaymentProcessor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public sealed class PaymentAdapter : IPaymentProcessor
{
    private readonly LegacyPaymentService _legacyPaymentService;

    public PaymentAdapter(LegacyPaymentService legacyPaymentService)
    {
        _legacyPaymentService = legacyPaymentService;
    }

    public void ProcessPayment(decimal amount)
    {
        string amountString = amount.ToString("F2");
        _legacyPaymentService.MakePayment(amountString);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;🏗️ 4️⃣ Criamos o Worker Service PaymentWorker&lt;/p&gt;

&lt;p&gt;Nosso Worker será responsável por chamar o IPaymentProcessor periodicamente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Threading;
using System.Threading.Tasks;

public class PaymentWorker : BackgroundService
{
    private readonly ILogger&amp;lt;PaymentWorker&amp;gt; _logger;
    private readonly IPaymentProcessor _paymentProcessor;

    public PaymentWorker(ILogger&amp;lt;PaymentWorker&amp;gt; logger, IPaymentProcessor paymentProcessor)
    {
        _logger = logger;
        _paymentProcessor = paymentProcessor;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation("Iniciando processamento de pagamento...");

            _paymentProcessor.ProcessPayment(100.50m); // Simulando pagamento de R$100,50

            _logger.LogInformation("Pagamento processado com sucesso!");

            await Task.Delay(5000, stoppingToken); // Executa a cada 5 segundos
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;🏗️ 5️⃣ Configuramos a Injeção de Dependência no Host&lt;/p&gt;

&lt;p&gt;Agora precisamos configurar os serviços no Host do Worker Service.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

class Program
{
    static void Main(string[] args)
    {
        var host = Host.CreateDefaultBuilder(args)
            .ConfigureServices((hostContext, services) =&amp;gt;
            {
                services.AddSingleton&amp;lt;LegacyPaymentService&amp;gt;(); // Serviço legado
                services.AddSingleton&amp;lt;IPaymentProcessor, PaymentAdapter&amp;gt;(); // Adapter
                services.AddHostedService&amp;lt;PaymentWorker&amp;gt;(); // Worker Service
                services.AddLogging(); // Logs
            })
            .Build();

        host.Run();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;✅ O que aprendemos?&lt;/p&gt;

&lt;p&gt;✔ Como usar o Adapter Pattern para conectar serviços legados a um código moderno.&lt;br&gt;
✔ Como estruturar Injeção de Dependência (DI) para desacoplar o código.&lt;br&gt;
✔ Como criar um Worker Service que processa tarefas periodicamente.&lt;/p&gt;




&lt;p&gt;🚀 Conclusão&lt;/p&gt;

&lt;p&gt;O Adapter Pattern é uma solução poderosa para integrar serviços sem alterar o código legado. Combinado com Injeção de Dependência e Worker Services, ele nos permite construir sistemas escaláveis e bem estruturados.&lt;/p&gt;

&lt;p&gt;E você? Já usou esse padrão em algum projeto? Deixe um comentário! 🚀&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>designpatterns</category>
      <category>dotnet</category>
    </item>
  </channel>
</rss>
