Injection of dependency Generics<T>

Asked

Viewed 565 times

3

Good morning friends. I hit a rough patch and I’m not getting past it.

I have 2 projects, a webapi and a standard class, both in dot net core.

In my standard design, I am working with Repository to abstract CRUD in mongoDB.

Follows the classes of the Repository:

INTERFACE

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace Model.Repository
{
    public interface IRepositoryMongo<TEntity> where TEntity : Mongo.MongoID
    {
         void Add(string identificador, TEntity entity);
         void AddAll(string identificador, List<TEntity> entity);
         void Edit(string identificador, TEntity entity);
         void Delete(string identificador, TEntity entity);
         List<TEntity> Get(string identificador, Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null); 
    }
}

Implementation

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using MongoDB.Bson;
using MongoDB.Driver;
using Microsoft.Extensions.Configuration;

namespace Model.Repository
{
    public class RepositoryMongo<TEntity> : IRepositoryMongo<TEntity> where TEntity : Mongo.MongoID
    {
        private MongoDB.Driver.IMongoDatabase dataBase;

        public RepositoryMongo(IConfiguration configuration)
        {
            var client = new MongoDB.Driver.MongoClient(configuration.GetConnectionString("defaultConnection"));
            this.dataBase = client.GetDatabase(configuration.GetConnectionString("dataBaseName"));
        }

        public void Add(string identificador, TEntity entity)
        {
            var dados = this.dataBase.GetCollection<TEntity>(typeof(TEntity).Name + "_" + identificador);
            dados.InsertOne(entity);
        }
        public void AddAll(string identificador, List<TEntity> entity)
        {
            var dados = this.dataBase.GetCollection<TEntity>(typeof(TEntity).Name + "_" + identificador);
            dados.InsertMany(entity);
        }
        public void Edit(string identificador, TEntity entity)
        {
            var dados = this.dataBase.GetCollection<TEntity>(typeof(TEntity).Name + "_" + identificador);
            var filtro = Builders<TEntity>.Filter.Eq("_id", entity.Id);
            dados.ReplaceOne(filtro, entity);
        }
        public void Delete(string identificador, TEntity entity)
        {
            var dados = this.dataBase.GetCollection<TEntity>(typeof(TEntity).Name + "_" + identificador);
            var filtro = Builders<TEntity>.Filter.Eq("_id", entity.Id);
            dados.DeleteOne(filtro);
        }

        public virtual List<TEntity> Get(string identificador, Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null)
        {
            var dados = this.dataBase.GetCollection<TEntity>(typeof(TEntity).Name + "_" + identificador);
            return dados.Find<TEntity>(new BsonDocument()).ToList();
        }
    }
}

Class of Mongo to force ID use on everything

using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using Newtonsoft.Json;

namespace Model.Mongo
{
    public class MongoID
    {
        [BsonId]
        [BsonRepresentation(BsonType.ObjectId)]
        public string Id { get; set; }
    }
}

So in the startup.Cs of my webAPI, I do the following::

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.IO;

namespace loginAPI
{
    public class Startup
    {

        public IConfiguration Configuration { get; set; }
        public IConfiguration minhaConfiguracao {get;set;}

        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;

            // evitar possiveis conflitos da configuração default
            this.minhaConfiguracao = new ConfigurationBuilder()
                .SetBasePath(System.IO.Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json")
                .Build();
        }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();

            // aqui está funcionando perfeitamente 
            services.AddSingleton<IConfiguration>(this.minhaConfiguracao);

            // aqui se eu não instanciar o tipo, ele da erro
            services.AddScoped<Model.Repository.IRepositoryMongo<Model.Login.Login>, Model.Repository.RepositoryMongo<Model.Login.Login>>();

            // tentei fazer isso aqui e nao deu certo:
            //services.AddScoped<Model.Repository.IRepositoryMongo<Model.Mongo.MongoID>, Model.Repository.RepositoryMongo<Model.Mongo.MongoID>>();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseMvc();
        }
    }
}

And finally, my controller:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;

namespace loginAPI.Controllers
{
    [Route("api/[controller]")]
    public class ValuesController : Controller
    {
        Model.Repository.IRepositoryMongo<Model.Login.Login> repository;

        public ValuesController(Model.Repository.IRepositoryMongo<Model.Login.Login> repository)
        {
            this.repository = repository;
        }

        // GET api/values
        [HttpGet]
        public IActionResult Get()
        {
            return Ok(this.repository.Get(""));
        }

        // GET api/values/5
        [HttpGet("{id}")]
        public string Get(int id)
        {
            return "value";
        }

        // POST api/values
        [HttpPost]
        public IActionResult Post([FromBody]Model.Login.Login value)
        {
            this.repository.Add("",value);
            return Ok (value);
        }

        // PUT api/values/5
        [HttpPut("{id}")]
        public void Put(int id, [FromBody]Model.Login.Login value)
        {
        }

        // DELETE api/values/5
        [HttpDelete("{id}")]
        public void Delete(int id)
        {
        }
    }
}

I want to know if there is any way to do the injection in a generic way, because all the types that I will use will necessarily inherit from Mongoid

So I don’t want to keep doing

services.AddScoped<Model.Repository.IRepositoryMongo<Model.x>, Model.Repository.RepositoryMongo<Model.x>>();

For every model I use in my controller/service

1 answer

1

You can use the typeof:

services.Addscoped(typeof(Irepositorymongo<>), typeof(Repositorymongo<>));

Browser other questions tagged

You are not signed in. Login or sign up in order to post.