Невозможно разрешить GraphQL.Resolvers.ICountriesResolver от корневого поставщика, так как для него требуется служба с ограниченным доступом Query.Persistence.SampleDbContext. - PullRequest
0 голосов
/ 17 октября 2019

Я работаю над проектом разработки API с использованием ASP.NET Core 2.2, GraphQL.NET, CosmosDB, EntityFrameworkCore (Microsoft.EntityFrameworkCore.Cosmos (2.2.4).

При запуске решения я вижуошибка:

Невозможно разрешить 'GraphQL.Resolvers.ICountriesResolver' от корневого поставщика, так как для него требуется служба с ограничением по объему 'Query.Persistence.SampleDbContext'.

Вот мои данные кода:

Startup.cs

 public void ConfigureServices(IServiceCollection services)
 {
        string serviceEndPoint = this.Configuration.GetValue<string>("CosmosDBEndpoint");
        string authKeyOrResourceToken = this.Configuration.GetValue<string>("CosmosDBAccessKey");
        string databaseName = this.Configuration.GetValue<string>("CosmosDBName");
        services.AddEntityFrameworkCosmos();
        services.AddDbContext<SampleDbContext>(options => options.UseCosmos(serviceEndPoint, authKeyOrResourceToken, databaseName, contextOptions =>
        {
            contextOptions.ExecutionStrategy(d => new CosmosExecutionStrategy(d));
        }

        ));
        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        services.AddSingleton<IDocumentExecuter, DocumentExecuter>();
        services.AddSingleton<IUtilityService, UtilityService>();
        services.AddTransient<ICommonService, CommonService>();
        services.AddTransient<ICountryService, CountryService>();
        services.AddSingleton<CountryResultType>();
        services.AddSingleton<GraphQLQuery>();
        services.AddTransient<ICountriesResolver, CountriesResolver>();
        services.AddSingleton<CountryType>();
        services.AddSingleton<Response>();
        services.AddScoped(typeof(ResponseGraphType<>));
        services.AddScoped(typeof(ResponseListGraphType<>));
        services.AddSingleton<IDataLoaderContextAccessor, DataLoaderContextAccessor>();
        services.AddSingleton<DataLoaderDocumentListener>();
        services.AddTransient<IAddressRepository, AddressRepository>();
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Latest);
        services.AddSingleton<SampleSchema>();
        var sp = services.BuildServiceProvider();
        services.AddSingleton<ISchema>(new SampleSchema(new FuncDependencyResolver(type => sp.GetService(type))));
} 

CountryResolver.cs

public class CountriesResolver : Resolver, ICountriesResolver
{
    private readonly ICountryService _countryService;
    private readonly IHttpContextAccessor _accessor;
    private readonly IUtilityService _utilityService;
    public CountriesResolver(ICountryService countryService, IHttpContextAccessor accessor, IUtilityService utilityService)
    {
        _countryService = countryService;
        _accessor = accessor;
        _utilityService = utilityService;
    }

    public void Resolve(GraphQLQuery graphQLQuery)
    {
        graphQLQuery.Field<ResponseGraphType<CountryResultType>>("countriesresponse", resolve: context =>
        {
            var locale = _utilityService.GetLocale(_accessor.HttpContext.Request.Headers);
            var list = _countryService.GetAllCountries(locale);
            return Response(list);
        }

        , description: "All Countries data");
    }
}

CountryService.cs

public class CountryService : ICountryService
{
    private readonly SampleDbContext _dbContext;
    private readonly ICommonService _commonService;
    private readonly IOptions<AppSettings> _appSettings;
    public CountryService(SampleDbContext dbContext, ICommonService commonService, IOptions<AppSettings> appSettings)
    {
        _dbContext = dbContext;
        _commonService = commonService;
        _appSettings = appSettings;
    }

    public async Task<CountryResult> GetAllCountries(string locale)
    {
        var result = new CountryResult();
        var language = _commonService.GetLanguageFromLocale(locale);
        var localeLangId = language.LanguageId;
        var dftLanguageId = int.Parse(_appSettings.Value.DefaultLanguageId);
        var dftDisplayName = await _dbContext.Countries.Where(cc => cc.IsPublished.Equals(true) && cc.LanguageId.Equals(dftLanguageId)).Select(df => df.DisplayNameShort).FirstOrDefaultAsync();
        var countries = await (_dbContext.Countries.Where(cc => cc.IsPublished.Equals(true) && cc.LanguageId.Equals(localeLangId)).Join(_dbContext.Disclaimers.Where(dc => dc.LanguageId.Equals(localeLangId)), c => c.CountryId, d => d.DefaultCountryId, (c, d) => new CountryDTO{Uuid = c.CountryId, DisplayName = c.DisplayName ?? dftDisplayName, DisplayNameShort = c.DisplayName ?? dftDisplayName, ProviderName = d.ProviderName, ProviderTerms = d.ProviderTerms, Name = dftDisplayName, Path = dftDisplayName, CompleteResponse = true}).ToListAsync());
        result.Countries = countries;
        return result;
    }
}

GraphQLQuery.cs

public class GraphQLQuery : ObjectGraphType
{
    public GraphQLQuery(IServiceProvider serviceProvider)
    {
        var type = typeof(IResolver);
        var resolversTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(s => s.GetTypes()).Where(p => type.IsAssignableFrom(p));
        foreach (var resolverType in resolversTypes)
        {
            var resolverTypeInterface = resolverType.GetInterfaces().Where(x => x != type).FirstOrDefault();
            if (resolverTypeInterface != null)
            {
                var resolver = serviceProvider.GetService(resolverTypeInterface) as IResolver;
                resolver.Resolve(this);
            }
        }
    }
}

Может кто-нибудь помочь мне решить эту проблему?

1 Ответ

1 голос
/ 21 октября 2019

Я быстро создал демонстрационное веб-приложение .net core 3.0 и протестировал его, как показано выше. Тем не менее, все было хорошо на моей стороне.

Классы CountryResolver и CountryService кажутся хорошими. Но вы не опубликовали свой класс SampleDbContext. Вы можете проверить это.

Вот мои фрагменты кода:

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();

    services.AddDbContext<CosmosDBContext>(options => options.UseCosmos(
        "https://jackcosmos.documents.azure.com:443/",
        "Y1tiY********lJurBg==",
        "DB"
    ));

    services.AddTransient<IMyService, MyService>();
    services.AddTransient<IMyResolver, MyResolver>();
}

CosmosDBContext.cs

Для удобства я только что протестировал с Cosmos DB SQL API. Но это не должно влиять на DI:

public class CosmosDBContext : DbContext
{
    public CosmosDBContext(DbContextOptions<CosmosDBContext> options) : base(options)
    {

    }

    public DbSet<Item> Items { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.HasDefaultContainer("Item");
    }
}

public class Item
{
    public Item(string key, string content) => (this.key, this.content) = (key, content);

    public string id { get; set; } = Guid.NewGuid().ToString();
    public string key { get; set; }
    public string content { get; set; }
}

MyService.cs

public class MyService : IMyService
{
    private CosmosDBContext _cosmosDbContext;

    public MyService(CosmosDBContext cosmosDBContext)
    {
        _cosmosDbContext = cosmosDBContext;
    }

    public List<Item> GetByKey(string key)
    {
        return _cosmosDbContext.Items.Where(i => i.key.Equals(key)).ToList();
    }
}

MyResolver.cs

public class MyResolver : IMyResolver
{
    private IMyService _myService;

    public MyResolver(IMyService myService)
    {
        _myService = myService;
    }

    public List<Item> Resolve(string key)
    {
        return _myService.GetByKey(key);
    }
}

А в моем HomeController я просто:

private IMyResolver _myResolver;

public HomeController(ILogger<HomeController> logger, CosmosDBContext cosmosDBContext, IMyResolver myResolver)
{
    _myResolver = myResolver;

    // Add one
    cosmosDBContext.Database.EnsureCreated();
    cosmosDBContext.Items.Add(new Item("aaa", "abcdefg"));
    cosmosDBContext.SaveChanges(true);

    _logger = logger;
}

public IActionResult Index()
{
    var result = _myResolver.Resolve("aaa");
    return Ok(JsonConvert.SerializeObject(result));
}

Выход:

enter image description here

...