Asp.net ядро ​​пользовательские IRouter Dependency Injection - PullRequest
0 голосов
/ 03 мая 2018

Я создаю собственную маршрутизацию в asp.net core 2, где проверяю путь в БД и обновляю действие и контроллер до желаемого.

У меня есть этот пользовательский IRouter, определенный так

public interface IRouteCustom : IRouter
{
}

public class RouteCustom : IRouteCustom
{
    private readonly IRouter _innerRouter;
    private readonly IMemoryCache _memoryCache;
    private readonly IUnitOfWork _unitOfWork;

    public RouteCustom(IRouter innerRouter, IMemoryCache memoryCache, IUnitOfWork unitOfWork)
    {
        _innerRouter = innerRouter ?? throw new ArgumentNullException(nameof(innerRouter));
        _memoryCache = memoryCache;
        _unitOfWork = unitOfWork;
    }

    public async Task RouteAsync(RouteContext context)
    {
        I check the routes in the DB using the _unitOfWork   
    }

    public VirtualPathData GetVirtualPath(VirtualPathContext context)
    {
        Also I do the same here...
    }

}

У меня нет проблем с этими функциями, и я могу выбрать контроллер и действие.

Моя проблема в том, как получить доступ к базе данных, поскольку я не могу внедрить зависимость IUnitOfWork в настраиваемый маршрутизатор.

Я получаю это сообщение об ошибке:

'Cannot resolve 'IUnitOfWork' from root provider because it requires scoped service 'DbContext'.'

У меня есть такие ConfigureServices, как это

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<DbContext>(options => options.UseMySQL(configuration.GetConnectionString("DefaultClient")));
    services.AddIdentity<Domain.EntitiesClient.Entities.ApplicationUser, Domain.EntitiesClient.Entities.ApplicationRole>().AddEntityFrameworkStores<DbContext>().AddDefaultTokenProviders();

    services.AddScoped<IDbContext, DbContext>();
    services.AddTransient<IUnitOfWork, UnitOfWork>();

    services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
    services.AddMemoryCache();

    services.AddMvc();

    /*route custom*/
    var supportedCultures = new[] { new CultureInfo("en-US"), new CultureInfo("es-ES"), new CultureInfo("it-IT") };
    var optionsCulture = new RequestLocalizationOptions { DefaultRequestCulture = new RequestCulture("en-US", "en-US"), SupportedCultures = supportedCultures, SupportedUICultures = supportedCultures };

    optionsCulture.RequestCultureProviders = new IRequestCultureProvider[] { new RouteDataRequestCultureProvider() { RouteDataStringKey = "culture", Options = optionsCulture } };
    services.AddSingleton(optionsCulture);

}

И Настроить

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseBrowserLink();
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
    }

    app.UseStaticFiles();
    app.UseAuthentication();

    app.UseMvc(routes =>
    {
        routes.Routes.Add(new RouteCustom(routes.DefaultHandler
            , routes.ServiceProvider.GetRequiredService<IMemoryCache>()
            , app.ApplicationServices.GetService<IUnitOfWork>()
            ));
        routes.MapRoute(name: "areas", template: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
        routes.MapRoute(name: "default", template: "{controller=Home}/{action=Index}/{id?}");
        });
}

Проблема здесь

app.ApplicationServices.GetService<IUnitOfWork>()

Мне нужно ввести IUnitOfWork, чтобы проверить базу данных, но я не знаю, как это сделать. В других промежуточных программах я мог внедрить IUnitOfWork непосредственно в функцию, но в этом случае я не могу сделать это в

публичная асинхронная задача RouteAsync (контекст RouteContext)

Как мне этого добиться? Я уверен, что я делаю что-то здесь не так, но я читал много статей и не могу найти способ.

Спасибо.

ОБНОВЛЕНИЕ: ВОЗМОЖНОЕ РЕШЕНИЕ

Единственное решение, о котором я могу подумать, - это удалить инъекцию в IRouter и получить службу «вручную» внутри метода RouteAsync.

public async Task RouteAsync(RouteContext context)
{
    var unitOfWork = context.HttpContext.RequestServices.GetRequiredService<IUnitOfWork>()
    var routes = unitOfWork.Router.GetAll();
    ...
}

Таким образом, у нас есть доступ к базе данных, и она работает хорошо. Это хороший подход?

...