簡體   English   中英

ASP.NET Core通用主機(HostBuilder)嘗試激活時無法解析類型…的服務

[英]ASP.NET Core Generic Host (HostBuilder) Unable to resolve service for type … while attempting to activate

我的意圖僅僅是使用通用主機在控制台應用程序中從另一個服務調用一個微服務。

它在運行時失敗,並帶有以下異常。 我已經閱讀了數十篇有關WebHostBuilder的帖子,但無法將討論與我要使用HostBuilder進行的工作聯系起來。 我顯然錯過了一些基本知識,非常感謝您的指導。 人為設計的代碼示例如下。 PS我相信我已經做了適當的格式化和標記工作,以安撫真正知道自己在做什么的人-顯然我不知道!

例外

System.InvalidOperationException:“在嘗試激活“ MyNoobProject.DoSomethingWithToDo”時,無法解析類型為“ MyNoobProject.IToDo”的服務。

Program.cs中

using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

public static async Task Main(string[] args)
    {
        var builder = new HostBuilder()
            .ConfigureServices((hostContext, services) =>
            {
                services.AddSingleton<IHostedService, ToDo>();
                services.AddSingleton<IHostedService, DoSomethingWithToDo>();

            })                
            .ConfigureLogging((hostingContext, logging) => {
               logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
                logging.AddConsole();
            });;

        await builder.RunConsoleAsync();
    }

StackOverflow.cs

using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;

namespace MyNoobProject
{
interface IToDo
{
    Task Add(int i);
    void Dispose();
}

class ToDo : IHostedService, IDisposable, IToDo
{
    private BlockingCollection<int> _blockingCollection;

    private readonly ILogger _logger;

    public ToDo(ILogger<ToDo>logger)
    {
        _logger = logger;
    }

    public Task Add(int i)
    {
        _blockingCollection.Add(i);
        return Task.CompletedTask;
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _blockingCollection = new BlockingCollection<int>();
        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        _blockingCollection.CompleteAdding();
        return Task.CompletedTask;
    }

    public void Dispose()
    {
        _blockingCollection.Dispose();
    }
}

interface IDoSomethingWithToDo
{

}

class DoSomethingWithToDo : IHostedService, IDisposable, IDoSomethingWithToDo
{
    private IToDo _todo;

    public DoSomethingWithToDo(IToDo todo)
    {
        _todo = todo;
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _todo.Add(1);
        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        return Task.CompletedTask;
    }

    public void Dispose()
    {

    }
}
}

服務提供者無法解析IToDo接口,因為它沒有在服務集合中注冊。

因此,您已經將ToDo實現注冊為單例托管服務。

services.AddSingleton<IHostedService, ToDo>();
services.AddSingleton<IHostedService, DoSomethingWithToDo>();

如果您想在其他服務的構造函數中使用接口,我建議對其進行一些重組。

由於該服務具有簡單的構造函數,因此您可以在組合根目錄中對其進行初始化,並應用必要的注冊

var todo = new ToDo();
services.AddSingleton<IToDo>(todo);
services.AddSingleton<ToDo>(todo);
services.AddSingleton<IHostedService>(todo);
services.AddSingleton<IHostedService, DoSomethingWithToDo>();

這樣,注入到DoSomethingWithToDo的構造函數中的接口將使用啟動時定義的單例

如果ToDo也通過構造函數注入具有依賴關系,則它可以遵循類似的模式,但是現在我們需要使用委托工廠來推遲初始化,以便可以解析和注入依賴關系。

//adding implementation first
services.AddSingleton<ToDo>();
//adding options for interfaces
services.AddSingleton<IToDo>(_ => _.GetService<ToDo>());
services.AddSingleton<IHostedService>(_ => _.GetService<ToDo>());
//...
services.AddSingleton<IHostedService, DoSomethingWithToDo>();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM