Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

asp.net core, Ef core : Dynamically map repository and services in run time

I have been mapping my repository class to its interface and same goes for services. Here I could manually register them. But I would like my code to dynamically map these in run time so that I don't have to manually register them every time I create a new repository or service. How can I achieve that?

Here's my code:

public void RegisterDependencies(IServiceCollection services, IConectionSetting connectionSetting)
{
    services.AddDbContext<QuantumDbContext>(options => options.UseSqlServer(connectionSetting.Get()));
    //services.AddDbContext<TestDbContext>(options => options.UseSqlServer(databaseFactory.ConnectionString));
    services.AddTransient<IDatabaseFactory, DatabaseFactory>();
    services.AddTransient<IDbContext, TestDbContext>();
    services.AddTransient<IDbContext, QuantumDbContext>();
    services.AddTransient<IUnitOfWorkManager, UnitOfWorkManager>();
    services.AddTransient<IRepository<CodeTable>, Repository<CodeTable>>();
    services.AddTransient<IRepository<Country>, Repository<Country>>();
    services.AddTransient<IRepository<State>, Repository<State>>();
    services.AddTransient<IRepository<City>, Repository<City>>();

    services.AddTransient<ICodeTableService, CodeTableService>();
    services.AddTransient<ICountryService, CountryService>();
}
like image 658
Avishekh Bharati Avatar asked Jun 23 '16 09:06

Avishekh Bharati


1 Answers

Let me split your question into two question:

1- How to register and resolve generic types in asp.net core with built-in DI library?

(see vNext Dependency Injection Generic Interface)

services.AddTransient<IRepository<CodeTable>, Repository<CodeTable>>();
services.AddTransient<IRepository<Country>, Repository<Country>>();
services.AddTransient<IRepository<State>, Repository<State>>();

You can simply register repositories like this:

services.AddTransient(typeof(IRepository<>), typeof(Repository<>));

2- How to implement batch registration(convention based) in asp.net core with built-in DI library? (see Convention based binding in ASP.NET 5 / MVC 6 )

services.AddTransient<ICodeTableService, CodeTableService>(); 
services.AddTransient<ICountryService, CountryService>();

I use following code to implement batch registration and it works as expected but i am not sure if it is good way(there may be wrong code in this implementation):

        // i assume your service interfaces inherit from IService
        Assembly ass = typeof(ICodeTableService).GetTypeInfo().Assembly;

        // get all concrete types which implements IService
        var allServices = ass.GetTypes().Where(t =>
            t.GetTypeInfo().IsClass && 
            !t.GetTypeInfo().IsAbstract &&
            typeof(IService).IsAssignableFrom(t));

        foreach (var type in allServices)
        {           
            var allInterfaces = type.GetInterfaces();
            var mainInterfaces = allInterfaces.Except
                    (allInterfaces.SelectMany(t => t.GetInterfaces()));
            foreach(var itype in mainInterfaces)
            {
                if (allServices.Any(x => !x.Equals(type) && itype.IsAssignableFrom(x)))
                {
                    throw new Exception("The " + itype.Name + " type has more than one implementations, please change your filter");
                }
                services.AddTransient(itype, type);
            }
        } 
like image 55
adem caglin Avatar answered Oct 15 '22 05:10

adem caglin