依赖注入在.NET Core中 - InvalidOperationException

5
我正在学习.NET Core,并且尝试在startup.cs中使用IServiceCollection来解决我的依赖关系。我在我的控制器中注入一个依赖项,该依赖项被解析为一个也具有注入依赖项的类。基本上,我因为无法激活依赖项而得到了InvalidOperationException异常。
这是我的堆栈跟踪:
InvalidOperationException: Unable to resolve service for type 'TestApplication.Services.LoginHttpService' while attempting to activate 'TestApplication.Services.LoginService'.

    Microsoft.Extensions.DependencyInjection.ServiceLookup.Service.PopulateCallSites(ServiceProvider provider, ISet<Type> callSiteChain, ParameterInfo[] parameters, bool throwIfCallSiteNotFound)   

    Microsoft.Extensions.DependencyInjection.ServiceLookup.Service.PopulateCallSites(ServiceProvider provider, ISet<Type> callSiteChain, ParameterInfo[] parameters, bool throwIfCallSiteNotFound)
    Microsoft.Extensions.DependencyInjection.ServiceLookup.Service.CreateCallSite(ServiceProvider provider, ISet<Type> callSiteChain)
    Microsoft.Extensions.DependencyInjection.ServiceProvider.GetResolveCallSite(IService service, ISet<Type> callSiteChain)
    Microsoft.Extensions.DependencyInjection.ServiceProvider.GetServiceCallSite(Type serviceType, ISet<Type> callSiteChain)
    Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(Type serviceType, ServiceProvider serviceProvider)
    System.Collections.Concurrent.ConcurrentDictionaryExtensions.GetOrAdd<TKey, TValue, TArg>(ConcurrentDictionary<TKey, TValue> dictionary, TKey key, Func<TKey, TArg, TValue> valueFactory, TArg arg)
    Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType)
    Microsoft.Extensions.Internal.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, bool isDefaultParameterRequired)
    lambda_method(Closure , IServiceProvider , Object[] )
    Microsoft.AspNetCore.Mvc.Internal.TypeActivatorCache.CreateInstance<TInstance>(IServiceProvider serviceProvider, Type implementationType)
    Microsoft.AspNetCore.Mvc.Controllers.DefaultControllerFactory.CreateController(ControllerContext context)
    Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
    Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+<InvokeNextResourceFilter>d__22.MoveNext()
    System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
    Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ResourceExecutedContext context)
    Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
    Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+<InvokeAsync>d__20.MoveNext()
    System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
    System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    Microsoft.AspNetCore.Builder.RouterMiddleware+<Invoke>d__4.MoveNext()
    System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
    System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    Microsoft.AspNetCore.Authentication.AuthenticationMiddleware+<Invoke>d__18.MoveNext()
    System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
    Microsoft.AspNetCore.Authentication.AuthenticationMiddleware+<Invoke>d__18.MoveNext()
    System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
    System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    Microsoft.VisualStudio.Web.BrowserLink.BrowserLinkMiddleware+<ExecuteWithFilter>d__7.MoveNext()
    System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
    System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware+<Invoke>d__7.MoveNext()

我的启动类已注册依赖项:

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddMvc();

    // Added - uses IOptions<T> for your settings.
    services.AddOptions();

    // Added - Confirms that we have a home for our DemoSettings
    services.Configure<UrlConfigurations>(Configuration.GetSection("UrlConfigurations"));

    //services.AddSingleton<ITokenProvider, Tokenpro>();

    services.AddTransient<ILoginService, LoginService>();
    services.AddSingleton<IHttpService, HttpService>();
    services.AddSingleton<ILoginHttpService, LoginHttpService>();

    services.AddSingleton<IUrlConfigurations, UrlConfigurations>();
    services.AddSingleton<IJsonDeserializer, JsonDeserializer>();
    services.AddSingleton<IHttpClientFactory, HttpClientFactory>();

    services.AddSingleton<IJsonValidator, JsonValidator>();
}

一旦运行时错误解决,我将更改范围(短暂的、单例的等)为正确的类型。

我的登录控制器:

using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using TestApplication.Configurations;
using TestApplication.Interfaces.Configurations;
using TestApplication.Interfaces.Services;
using TestApplication.Models;

// For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860

namespace TestApplication.Controllers
{
    public class LoginController : Controller
    {
        private readonly ILoginService _loginService;
        private readonly IUrlConfigurations _urlConfigurations;

        public LoginController(ILoginService loginService, IOptions<UrlConfigurations> urlConfigurations)
        {
            _loginService = loginService;
            _urlConfigurations = urlConfigurations.Value;
        }

        public async Task<IActionResult> Index()
        {
            var jsonWebToken = await GetJsonWebToken();
            return View();
        }

        private async Task<JwtSecurityToken> GetJsonWebToken()
        {
            // get token - hard-coded for now
            var login = new LoginViewModel { Username = "xsurajit.kar@thomastelford.comx", Password = "marshwall" };
            var jsonWebToken = await _loginService.Login(login);
            return jsonWebToken;
        }
    }
}

我使用的登录服务是 LoginHttpService

using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using TestApplication.Configurations;
using TestApplication.Interfaces.Configurations;
using TestApplication.Interfaces.Services;
using TestApplication.Models;

namespace TestApplication.Services
{
    public class LoginService : ILoginService
    {
        private readonly LoginHttpService _loginHttpService;
        private readonly IUrlConfigurations _urlConfigurations;

        public LoginService(LoginHttpService loginHttpService, IOptions<UrlConfigurations> urlConfigurations)
        {
            _loginHttpService = loginHttpService;
            _urlConfigurations = urlConfigurations.Value;

        }

        public async Task<JwtSecurityToken> Login(LoginViewModel login)
        {
            login.LoginMapper();
            var response = await _loginHttpService.PostLoginAsync(_urlConfigurations.GetToken, login.EncodedLoginDetailsContent);

            if (response == null) return null;

            var data = await response.Content.ReadAsStringAsync();
            // Deserialize JWT
            var accessToken = JsonConvert.DeserializeObject<UserResponseModel>(data)?.access_token;

            if (string.IsNullOrEmpty(accessToken) || !response.IsSuccessStatusCode) return null;

            // Cast JWT to correct class
            var securityToken = new JwtSecurityTokenHandler().ReadToken(accessToken) as JwtSecurityToken;

            return securityToken;
        }
    }
}

有人知道我在startup.cs类中做错了什么吗?我想解决TestApplication.Services.LoginService中使用的TestApplication.Services.LoginHttpService问题。

2个回答

8
public LoginService(LoginHttpService loginHttpService, IOptions<UrlConfigurations> urlConfigurations)
{
    _loginHttpService = loginHttpService;
    _urlConfigurations = urlConfigurations.Value; 
}

LoginService类构造函数中的LoginHttpService更改为接口ILoginHttpService

这样应该就可以了。


谢谢!我没有看到那个错字。我以为在启动时需要做一些不同的事情。 - nick gowdy

6

在我的情况下,我忘记在Startup.cs中添加上下文服务:

services.AddDbContext<My_ScaffoldingContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MyConnectionString")));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接