Blazor:尝试激活yyy时无法解析xx类型的服务

时间:2019-06-13 20:48:32

标签: c# dependency-injection blazor

我已经阅读了关于同一主题的许多其他SO问题,但是我发现的答案都不适用于我的情况,所以去了:

我已经在Startup.cs中成功添加了4个服务,并且之前运行良好。然后我添加了第5个,现在我意识到有些问题了-所有服务都不起作用。即使我完全删除了第五个,其他两个现在也被破坏了,并且出现了相同的错误。

  

尝试激活时无法解析xx类型的服务

这是我的Startup.cs ConfigureServices.cs:

public void ConfigureServices(IServiceCollection services)
{
    services.AddStorage();
    services.AddSingleton<IMyLocalStorage, MyLocalStorage>();
    services.AddSingleton<IFrontEndService, FrontEndService>();
    services.AddSingleton<ISystemProvider, SystemProviderService>();
    services.AddSingleton<IAuthenticationService, AuthenticationService>();
}

它是我注意到该错误的最后一个AuthenticationService,但是现在即使是以前运行的旧服务也失败了。

public interface IAuthenticationService
{
   // ... 
}

public class AuthenticationService : IAuthenticationService
{
    private readonly FrontEndService frontEndService;
    private readonly MyLocalStorage myLocalStorage;

    public AuthenticationService(FrontEndService frontEndService, MyLocalStorage myLocalStorage)
    {
        this.frontEndService = frontEndService;
        this.myLocalStorage = myLocalStorage;
    }

    // ...
}

服务很简单;一个接口,该接口的一种实现,然后添加Startup.cs。我不知道为什么它停止工作。

因此,如果我删除IAuthenticationService,则会在FrontEndService中显示错误,然后在MyLocalStorage上进行抱怨:

public interface IFrontEndService
{
    Task<T> GetAsync<T>(string requestUri);
}

public class FrontEndService : IFrontEndService
{
    private readonly HttpClient client;
    private readonly MyLocalStorage myLocalStorage;

    public FrontEndService(HttpClient client, MyLocalStorage myLocalStorage)
    {
         // ...
    }
}

public class MyLocalStorage : IMyLocalStorage
{
    public MyLocalStorage(LocalStorage storage)
    {
        this.storage = storage;
    }
}

我在这里想念什么?

2 个答案:

答案 0 :(得分:2)

IServiceCollection上调用诸如.AddSingleton<IFrontEndService, FrontEndService>()之类的方法时,您对容器说:“每当看到IFrontEndService依赖项时,就插入FrontEndService的实例”。现在,请看一下您的AuthenticationService

public class AuthenticationService : IAuthenticationService
{
    private readonly FrontEndService frontEndService;
    private readonly MyLocalStorage myLocalStorage;

    public AuthenticationService(FrontEndService frontEndService, MyLocalStorage myLocalStorage)
    {
        this.frontEndService = frontEndService;
        this.myLocalStorage = myLocalStorage;
    }

    // ...
}

请注意如何传递FrontEndServiceMyLocalStorage的依赖项,而不是您注册的接口。这意味着容器无法识别它们,因此它不知道如何实现依赖关系图。

您需要更改服务以依赖于接口,因为这些是您在容器中注册的:

public class AuthenticationService : IAuthenticationService
{
    private readonly IFrontEndService frontEndService;
    private readonly IMyLocalStorage myLocalStorage;

    public AuthenticationService(IFrontEndService frontEndService, IMyLocalStorage myLocalStorage)
    {
        this.frontEndService = frontEndService;
        this.myLocalStorage = myLocalStorage;
    }

    // ...
}

答案 1 :(得分:1)

@Ted, 您还记得几周前在服务中使用LocalStorage的问题吗?在该服务处,您有一个带有IStorage参数的构造函数,但这会导致错误,原因是尽管LocalStorage类实现了IStorage接口,但此库的创建者将LocalStorage作为像这样的具体类添加到了DI容器中:

public static IServiceCollection AddStorage(this IServiceCollection services)
        {
            return services.AddSingleton<SessionStorage>()
                .AddSingleton<LocalStorage>();
        } 

因此,您必须使用

  

(本地存储存储)

代替

  

(IStorage存储)

上面的扩展方法可以这样重写:

public static IServiceCollection AddStorage(this IServiceCollection services)
            {
                return services.AddSingleton<IStorage, SessionStorage>()
                    .AddSingleton<IStorage, LocalStorage>();
            }  

在这种情况下,您可以在构造函数中使用IStorage接口。

现在您可以形成一般规则,并采取相应的行动。

Ted说:

  

那很奇怪,因为我之前完全使用过这种方法,而且   工作正常。如果您阅读文档,Microsoft也会使用具体的   类,而不是接口

HttpClient派生自HttpMessageInvoker。它没有实现任何接口。

此代码段显示了如何将HttpClient添加到服务容器中,以及如何将其注入到您的客户端Blazor中:

services.AddSingleton<HttpClient>(s =>
        {
            // Creating the URI helper needs to wait until the JS Runtime is initialized, so defer it.
            var uriHelper = s.GetRequiredService<IUriHelper>();
            return new HttpClient
            {
                BaseAddress = new Uri(WebAssemblyUriHelper.Instance.GetBaseUri())
            };
        });

希望这对您有帮助...