A injeção de dependência é um padrão de design que facilita a codificação. Ele evita o incômodo de instanciar objetos com dependências complexas e facilita a criação de testes. Com a Biblioteca Couchbase.Extensions.DependencyInjection (GitHub)Se você não tiver um plano de negócios, poderá usar clusters e buckets do Couchbase na estrutura de injeção de dependência do ASP.NET Core.
Em minha última postagem no blog sobre Cache distribuído com ASP.NETNa postagem anterior, mencionei a biblioteca DependencyInjection. A injeção de dependência será explorada em detalhes nesta postagem. Fique à vontade para acompanhar os exemplos de código que criei, disponíveis em GitHub.
Configuração básica do Couchbase
Primeiro, você precisará de um cluster do Couchbase Server em execução. Você pode:
- Instale-o no local
- Executar em um contêiner com o Docker
- Use um serviço de nuvem como Azure
Em seguida, você precisará criar um balde no Couchbase. Esse pode ser o bucket "travel-sample" fornecido com o Couchbase ou um bucket criado por você mesmo.
Se você estiver usando o Couchbase Server 5.0, também precisará criar um usuário. Dê a esse usuário a permissão Cluster Admin e dê a ele o mesmo nome do bucket, apenas para manter as coisas simples, caso esteja acompanhando o processo.
Injeção de dependência com o Couchbase.Extensions
O Couchbase.Extensions (GitHub) tem como objetivo tornar mais simples o trabalho com o Couchbase Server e o ASP.NET Core. A injeção de dependência é apenas uma dessas extensões.
Você pode adicioná-lo ao seu projeto ASP.NET Core com o NuGet:
- Usando o Package Manager:
Instalar o pacote Couchbase.Extensions.DependencyInjection -Versão 1.0.2
- Com a interface do usuário do NuGet
- Use a linha de comando do .NET:
dotnet add package Couchbase.Extensions.DependencyInjection --versão 1.0.2
(A versão 1.0.2 é a versão mais recente no momento da redação deste documento).
Em seguida, você precisará fazer alterações em seu Inicialização
classe em Startup.cs
.
Na postagem do blog sobre cache, eu codifiquei a configuração:
1 2 3 4 5 |
serviços.AddCouchbase(cliente => { cliente.Servidores = novo Lista<Uri> { novo Uri("http://localhost:8091")}; cliente.UseSsl = falso; }); |
Isso é bom para demonstrações e publicações em blogs, mas você provavelmente desejará usar um arquivo de configuração para um projeto de produção.
1 |
serviços.AddCouchbase(Configuração.GetSection("Couchbase")); |
Supondo que você esteja usando o padrão Configurações do aplicativo.json
atualize esse arquivo para adicionar uma seção do Couchbase:
1 2 3 4 5 6 |
"Couchbase" : { "Servidores": [ "http://localhost:8091" ], "UseSsl": falso } |
Ao criar uma seção "Couchbase", o módulo de injeção de dependência lerá diretamente do arquivo de texto appsettings.json.
Injeção de construtor
Depois que a injeção de dependência estiver configurada, você poderá começar a injetar objetos úteis em suas classes. Você pode injetá-los em controladores, serviços ou repositórios.
Aqui está um exemplo de injeção em HomeController
:
1 2 3 4 5 6 7 8 9 10 11 |
público classe HomeController : Controlador { privado somente leitura IBucket _bucket; público HomeController(IBucketProvider provedor de balde) { _bucket = provedor de balde.GetBucket("amostra de viagem", "senha"); } // ... snip ... } |
Em seguida, vamos fazer um simples Obter
em um documento conhecido em "travel-sample". Esse uso de token do SDK do Couchbase .NET mostrará a injeção de dependência em ação. Farei uma alteração no arquivo Sobre
método de ação. Nesse método, ele recuperará um documento de rota e escreverá o número do equipamento.
1 2 3 4 5 6 7 8 9 10 |
público IActionResult Sobre() { // obter o documento de rota de Columbus para Chicago (United) var rota = _bucket.Obter<dinâmico>("route_56027").Valor; // exibir o número do equipamento da rota Exibir dados["Mensagem"] = "CMH para ORD - " + rota.equipamentos; retorno Ver(); } |
E o resultado é:
Sucesso! A injeção de dependência funcionou e estamos prontos para usar um bucket do Couchbase.
Se não estiver usando "travel-sample", use uma chave do seu próprio bucket.
Baldes nomeados
Você pode usar a injeção de dependência para um único bucket em vez de ter que especificar o nome todas as vezes.
Comece criando uma interface que implemente INamedBucketProvider
. Deixe-o vazio. Aqui está um exemplo:
1 2 3 4 |
público interface ITravelSampleBucketProvider : INamedBucketProvider { // nada entra aqui! } |
Em seguida, em Startup.cs, mapeie essa interface para um bucket usando AddCouchbaseBucket
:
1 2 3 |
serviços .AddCouchbase(Configuração.GetSection("Couchbase")) .AddCouchbaseBucket<ITravelSampleBucketProvider>("amostra de viagem", "senha"); |
Agora, o ITravelSampleBucketProvider
é injetado em vez do provedor mais geral.
1 2 3 4 |
público HomeController(ITravelSampleBucketProvider provedor travelBucket) { _bucket = provedor travelBucket.GetBucket(); } |
Injeção de dependência mais complexa
Até este ponto, só usamos a injeção de dependência nos controladores. A injeção de dependência começa a render dividendos com gráficos de objetos mais complexos e profundos.
Como exemplo, imagine uma classe de serviço que usa um bucket do Couchbase, mas também usa um serviço de e-mail.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
público classe ComplexService : IComplexService { privado somente leitura IBucket _bucket; privado somente leitura IEmailService _email; público ComplexService(ITravelSampleBucketProvider provedor de balde, IEmailService emailService) { _bucket = provedor de balde.GetBucket(); _email = emailService; } público vazio ApproveApplication (aprovar aplicativo)(string emailAddress) { _bucket.Upsert(emailAddress, novo {emailAddress, aprovado = verdadeiro}); _email.SendEmail(emailAddress, "Aprovado", "Sua inscrição foi aprovada!"); } } |
Em seguida, vamos usar esse serviço em um controlador (ou seja, torná-lo uma dependência). Mas observe que o controlador não está usando diretamente o bucket ou o serviço de e-mail.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
público classe AprovarControlador : Controlador { privado somente leitura IComplexService _svc; público AprovarControlador(IComplexService serviço) { _svc = serviço; } público IActionResult Índice() { var fakeEmailAddress = Faker.Internet.E-mail(); _svc.ApproveApplication (aprovar aplicativo)(fakeEmailAddress); Exibir dados["Mensagem"] = "Aprovado '" + fakeEmailAddress + "'"; retorno Ver(); } } |
Se eu fosse instanciar ComplexService
manualmente, eu teria que instanciar pelo menos dois outros objetos. Seria algo parecido com: novo ComplexService(novo BucketProvider(), novo MyEmailService()
. É muita coisa que tenho que controlar e, se alguma dependência mudar, é preciso fazer muita manutenção manual.
Em vez disso, posso fazer com que o ASP.NET Core use a injeção de dependência para fazer tudo isso por mim. Voltar em Inicialização
:
1 2 |
serviços.AddTransient<IEmailService, MyEmailService>(); serviços.AddTransient<IComplexService, ComplexService>(); |
Agora, o ASP.NET Core sabe como instanciar:
ITravelSampleBucketProvider
graças ao Couchbase.Extensions.DependencyInjectionIEmailService
- Eu disse a ele para usarMyEmailService
IComplexService
- Eu disse a ele para usarComplexService
Por fim, quando AprovarControlador
for instanciado, o ASP.NET Core saberá como fazer isso. Ele criará ComplexService
ao instanciar MyEmailService
e ComplexService
. Ele injetará ComplexService
automaticamente no construtor do `ApproveController`. O resultado final:
Para ver o exemplo completo, não deixe de conferir o código-fonte que acompanha esta postagem do blog no GitHub.
Limpeza
Não se esqueça de fazer a limpeza. Quando o aplicativo ASP.NET Core for interrompido, libere todos os recursos que o SDK do Couchbase .NET estiver usando. Na seção Configurar
no Startup, adicione um parâmetro do tipo IApplicationLifetime
:
1 |
público vazio Configurar(IApplicationBuilder aplicativo, IHostingEnvironment env, ILoggerFactory loggerFactory, IApplicationLifetime tempo de vida do aplicativo) |
Dentro disso Configurar
configure um método ApplicationStopped
evento:
1 2 3 4 |
tempo de vida do aplicativo.ApplicationStopped.Registro(() => { aplicativo.ApplicationServices.GetRequiredService<ICouchbaseLifetimeService>().Fechar(); }); |
Resumo
A injeção de dependência é um assunto rico. Livros inteiros foram escritos sobre ela e seus benefícios para seu aplicativo. Esta postagem do blog apenas arranhou a superfície e nem sequer abordou os benefícios da testabilidade.
O Couchbase.Extensions.DependencyInjection facilita a injeção do Couchbase no ASP.NET Core.
Se você tiver perguntas ou comentários, não deixe de conferir o Repositório do GitHub ou o Fóruns do SDK do Couchbase .NET.
E entre em contato comigo para fazer perguntas, deixando um comentário abaixo ou encontrando-me em Twitter @mgroves.
ao tentar definir
ervices.AddCouchbase(Configuration.GetSection("Couchbase"));
usando configurações, a chamada para : Configuration.GetSection("Couchbase"))
retorna nulo.
Portanto, esse não é o problema.
Parece que os dados foram transmitidos corretamente, mas quando tento chamar:
bucketProvider.GetBucket("statistics", "");
Recebo a mensagem "Bootsrap exception".
Arthur, você poderia publicar sua pergunta, juntamente com uma visão mais completa do seu código, no fórum do Couchbase .NET: https://www.couchbase.com/forums/c/net-sdk
Olá, Matthew, você poderia atualizar o código do repositório? Estou tendo problemas para usá-lo em um projeto ASP.Net Core 2.2.
Claro, Lahbabi, acabei de atualizar o repositório para o .NET Core 2.2. É provável que você não esteja realmente tendo problemas com o .NET Core 2.2. Meu palpite é que você esteja usando o Couchbase Server 5 ou mais recente, que alterou a forma como a autenticação funciona. (O único problema do .NET Core que vi é que eu tinha algumas coisas do loggerFactory que foram descontinuadas desde o .NET Core 1).
Obrigado, Matthew, está funcionando. Consegui me autenticar, mas não consegui encontrar onde clicar para buscar os dados... a amostra de viagem já está instalada no banco de dados.
Como vi seu maravilhoso exemplo de lista de presentes CRUD simples, esperava ver algo semelhante, mas desta vez usando a injeção de dependência. Como posso obter esse tipo de coisa com a injeção de dependência?
Você tem razão quando diz que esse exemplo não abrange todas as operações CRUD, mas o SDK não mudou muito desde que fiz o vídeo a que você se refere. Se você verificar o HomeController neste repositório, verá que ele ainda é apenas um objeto IBucket sendo usado. https://github.com/couchbaselabs/blog-source-code/blob/master/Groves/078AspNetCoreDependencyInjection/src/CouchbaseDIExample/CouchbaseDIExample/Controllers/HomeController.cs#L42
Você se interessaria por um vídeo que mostrasse o .net core 2.2, a injeção de dependência, o crud e o Couchbase juntos?
Eu não chegaria ao ponto de lhe perguntar isso :) Acho que colocar a Injeção de Dependência em ação com a API Rest na demonstração da lista de desejos, mesmo que apenas modificando o código existente, seria muito útil para mim e para muitos desenvolvedores do .Net Core que desejam tocar e gostar de lidar com o Couchbase. O exemplo de código da lista de desejos com a introdução do N1QL é um ponto de partida muito simples e muito conciso para levar o Couchbase a uma maior popularidade na comunidade de desenvolvedores do .Net Core.
Obrigado, esse é um bom feedback. Há algum tempo não atualizo meu conteúdo de "introdução ao ASP.NET", talvez seja a hora.
[…] https://www.couchbase.com/dependency-injection-aspnet-couchbase/ https://docs.couchbase.com/dotnet-sdk/current/hello-world/start-using-sdk.html […]
[…] https://www.couchbase.com/dependency-injection-aspnet-couchbase/ https://docs.couchbase.com/dotnet-sdk/current/hello-world/start-using-sdk.html […]