依赖注入错误:在类已注册时,试图激活时无法解析类型的服务

我创建了一个。net核心MVC应用程序,并使用依赖注入和存储库模式将存储库注入到我的控制器。然而,我得到一个错误:

无法解析类型为“WebApplication1.Data”的服务。当试图激活“WebApplication1.Controllers.BlogController”。

存储库:

public interface IBloggerRepository { ... }


public class BloggerRepository : IBloggerRepository { ... }

控制器:

public class BlogController : Controller
{
private readonly IBloggerRepository _repository;


public BlogController(BloggerRepository repository)
{
_repository = repository;
}


public IActionResult Index() { ... }
}

Startup.cs:

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

services.AddScoped<IBloggerRepository, BloggerRepository>();
}

我不知道我哪里做错了。什么好主意吗?

739106 次浏览

分解错误信息:

无法解析类型为“WebApplication1.Data”的服务。当试图激活“WebApplication1.Controllers.BlogController”。

这就是说,你的应用程序试图创建一个BlogController的实例,但它不知道如何创建一个BloggerRepository的实例来传递给构造函数。

现在看看你的创业公司:

services.AddScoped<IBloggerRepository, BloggerRepository>();

也就是说,每当需要IBloggerRepository时,创建一个BloggerRepository并将其传入。

然而,你的控制器类请求的是具体类BloggerRepository,而依赖注入容器在被直接请求时不知道该做什么。

我猜你只是打错了,但很常见。所以简单的解决方法是改变你的控制器来接受DI容器知道如何处理的东西,在这种情况下,就是接口:

public BlogController(IBloggerRepository repository)
//                    ^
//                    Add this!
{
_repository = repository;
}

注意,有些对象有自己的自定义注册方式,这在你使用外部Nuget包时更常见,所以阅读它们的文档是值得的。例如,如果你收到一条消息说:

无法解析类型为“Microsoft.AspNetCore.Http”的服务。IHttpContextAccessor”……

然后你可以使用该库提供的自定义扩展方法来修复它,它将是:

services.AddHttpContextAccessor();

对于其他包,请阅读文档。

只有当有人有和我一样的情况时,我正在用现有的数据库做一个EntityFramework教程,但是当在模型文件夹上创建新的数据库上下文时,我们需要在启动时更新上下文,而不仅仅是在服务中。AddDbContext和adddentity如果你有用户身份验证

services.AddDbContext<NewDBContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));


services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<NewDBContext>()
.AddDefaultTokenProviders();

在我的情况下,我试图为一个需要构造函数参数的对象做依赖注入。在这种情况下,在启动期间,我只是提供了配置文件的参数,例如:

var config = Configuration.GetSection("subservice").Get<SubServiceConfig>();
services.AddScoped<ISubService>(provider => new SubService(config.value1, config.value2));

如果您正在使用AutoFac并得到这个错误,您应该添加一个“As”语句来指定具体实现实现的服务。

Ie。你应该这样写:

containerBuilder.RegisterType<DataService>().As<DataService>();

而不是

containerBuilder.RegisterType<DataService>();

我有一个不同的问题,是的,我的控制器的参数化构造函数已经添加了正确的接口。我所做的很简单。我只是去到我的startup.cs文件,在那里我可以看到一个调用注册方法。

public void ConfigureServices(IServiceCollection services)
{
services.Register();
}

在我的例子中,这个Register方法在一个单独的类Injector中。所以我必须在那里添加我新引入的接口。

public static class Injector
{
public static void Register(this IServiceCollection services)
{
services.AddTransient<IUserService, UserService>();
services.AddTransient<IUserDataService, UserDataService>();
}
}

如果你看到,这个函数的参数是this IServiceCollection

希望这能有所帮助。

我得到这个问题是因为一个相当愚蠢的错误。我忘了在ASP中挂钩我的服务配置过程来自动发现控制器。NET核心应用程序。

添加这个方法解决了这个问题:

// Add framework services.
services.AddMvc()
.AddControllersAsServices();      // <---- Super important

我遇到了这个问题,因为在依赖注入设置中,我遗漏了一个存储库的依赖项,而这个依赖项是控制器的依赖项:

services.AddScoped<IDependencyOne, DependencyOne>();    <-- I was missing this line!
services.AddScoped<IDependencyTwoThatIsDependentOnDependencyOne, DependencyTwoThatIsDependentOnDependencyOne>();

你需要在启动时为DBcontext添加一个新服务

默认的

services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));

添加这个

services.AddDbContext<NewDBContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("NewConnection")));

为了工作,我不得不在ConfigureServices中添加这一行。

services.AddSingleton<IOrderService, OrderService>();

我已经不例外了

        System.InvalidOperationException: Unable to resolve service for type 'System.Func`1[IBlogContext]'
while attempting to activate 'BlogContextFactory'.\r\n at
Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type serviceType, Type implementationType, ISet`1 callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)\r\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(Type serviceType, Type implementationType, ISet`1 callSiteChain)\r\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, ISet`1 callSiteChain)\r\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(Type serviceType, ISet`1 callSiteChain)\r\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, ISet`1 callSiteChain)\r\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type serviceType, Type implementationType, ISet`1 callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)\r\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(Type serviceType, Type implementationType, ISet`1 callSiteChain)\r\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, ISet`1 callSiteChain)\r\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(Type serviceType, ISet`1 callSiteChain)\r\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, ISet`1 callSiteChain)\r\n at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(Type serviceType, ServiceProvider serviceProvider)\r\n at System.Collections.Concurrent.ConcurrentDictionaryExtensions.GetOrAdd[TKey, TValue, TArg] (ConcurrentDictionary`2 dictionary, TKey key, Func`3 valueFactory, TArg arg)\r\n at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType)\r\n at Microsoft.Extensions.Internal.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, Boolean isDefaultParameterRequired)\r\n at lambda_method(Closure , IServiceProvider , Object[] )\r\n at Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>c__DisplayClass5_0.<CreateControllerFactory>g__CreateController|0(ControllerContext controllerContext)\r\n at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)\r\n at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync()\r\n at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextExceptionFilterAsync()

因为我想注册工厂来创建DbContext派生类IBlogContextFactory的实例,并使用create方法来实例化BlogContext的实例,这样我就可以使用下面的模式以及依赖注入,也可以使用模拟进行单元测试。

我想用的模式是

public async Task<List<Blog>> GetBlogsAsync()
{
using (var context = new BloggingContext())
{
return await context.Blogs.ToListAsync();
}
}

但不是新的BloggingContext(),我想通过构造函数注入工厂,就像下面的BlogController类

    [Route("blogs/api/v1")]


public class BlogController : ControllerBase
{
IBloggingContextFactory _bloggingContextFactory;


public BlogController(IBloggingContextFactory bloggingContextFactory)
{
_bloggingContextFactory = bloggingContextFactory;
}


[HttpGet("blog/{id}")]
public async Task<Blog> Get(int id)
{
//validation goes here
Blog blog = null;
// Instantiage context only if needed and dispose immediately
using (IBloggingContext context = _bloggingContextFactory.CreateContext())
{
blog = await context.Blogs.FindAsync(id);
}
//Do further processing without need of context.
return blog;
}
}

这是我的服务注册码

            services
.AddDbContext<BloggingContext>()
.AddTransient<IBloggingContext, BloggingContext>()
.AddTransient<IBloggingContextFactory, BloggingContextFactory>();

下面是我的模型和工厂类

    public interface IBloggingContext : IDisposable
{
DbSet<Blog> Blogs { get; set; }
DbSet<Post> Posts { get; set; }
}


public class BloggingContext : DbContext, IBloggingContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }


protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseInMemoryDatabase("blogging.db");
//optionsBuilder.UseSqlite("Data Source=blogging.db");
}
}


public interface IBloggingContextFactory
{
IBloggingContext CreateContext();
}


public class BloggingContextFactory : IBloggingContextFactory
{
private Func<IBloggingContext> _contextCreator;
public BloggingContextFactory(Func<IBloggingContext> contextCreator)// This is fine with .net and unity, this is treated as factory function, but creating problem in .netcore service provider
{
_contextCreator = contextCreator;
}


public IBloggingContext CreateContext()
{
return _contextCreator();
}
}


public class Blog
{
public Blog()
{
CreatedAt = DateTime.Now;
}


public Blog(int id, string url, string deletedBy) : this()
{
BlogId = id;
Url = url;
DeletedBy = deletedBy;
if (!string.IsNullOrWhiteSpace(deletedBy))
{
DeletedAt = DateTime.Now;
}
}
public int BlogId { get; set; }
public string Url { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime? DeletedAt { get; set; }
public string DeletedBy { get; set; }
public ICollection<Post> Posts { get; set; }


public override string ToString()
{
return $"id:{BlogId} , Url:{Url} , CreatedAt : {CreatedAt}, DeletedBy : {DeletedBy}, DeletedAt: {DeletedAt}";
}
}


public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
public Blog Blog { get; set; }
}

-----在。net核心MVC项目中修复这个问题——我在依赖项注册上做了以下更改

            services
.AddDbContext<BloggingContext>()
.AddTransient<IBloggingContext, BloggingContext>()
.AddTransient<IBloggingContextFactory, BloggingContextFactory>(
sp => new BloggingContextFactory( () => sp.GetService<IBloggingContext>())
);

简而言之,在。net中,核心开发人员负责注入工厂函数,这在Unity和。net框架的情况下得到了照顾。

Public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IEventRepository, EventRepository>();
}

你忘了加上“服务”。AddScoped"在启动ConfigureServices方法。

我更换了

services.Add(new ServiceDescriptor(typeof(IMyLogger), typeof(MyLogger)));

services.AddTransient<IMyLogger, MyLogger>();

这对我很有效。

这个问题是因为您没有使用为其编写的接口注册数据访问组件。尝试使用以下方法

services.AddTransient<IMyDataProvider, MyDataAccess>();`

哦,谢谢@kimbaudi,我跟着这个tuts

https://dotnettutorials.net/lesson/generic-repository-pattern-csharp-mvc/

得到了和你一样的错误。但读了你的代码后,我发现我的解决方案是添加

服务。AddScoped (IGenericRepository GenericRepository);

在StartUp.cs file =)中导入ConfigureServices方法

在项目的Startup.cs文件的ConfigureServices方法中添加services.AddSingleton ();

public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
// To register interface with its concrite type
services.AddSingleton<IEmployee, EmployeesMockup>();
}

欲了解更多详情,请访问此URL: https://www.youtube.com/watch?v=aMjiiWtfj2M

对于所有方法(即AddSingleton vs AddScoped vs AddTransient)请访问此URL: https://www.youtube.com/watch?v=v6Nr7Zman_Y&list=PL6n9fhu94yhVkdrusLaQsfERmL_Jh4XmU&index=44)

我也有同样的问题,并发现我的代码在初始化之前使用了注入。

services.AddControllers(); // Will cause a problem if you use your IBloggerRepository in there since it's defined after this line.
services.AddScoped<IBloggerRepository, BloggerRepository>();

我知道这与问题无关,但自从我被送到这个页面,我发现它对其他人是有用的。

解析服务甚至在到达类代码之前就已经完成了,因此我们需要检查依赖注入。

就我而言,我补充道

        services.AddScoped<IMeasurementService, MeasurementService>();

在StartupExtensions.cs

在我的情况下,.Net Core 3.0 API在 Startup.cs, 在方法< / p >

public void ConfigureServices(IServiceCollection services)

我必须补充一点

services.AddScoped<IStateService, StateService>();

将BloggerRepository更改为IBloggerRepository

我有问题试图从我的Program.cs文件中注入,通过使用下面的CreateDefaultBuilder,但最终通过跳过默认绑定器来解决它。(见下文)。

var host = Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureServices(servicesCollection => { servicesCollection.AddSingleton<ITest>(x => new Test()); });
webBuilder.UseStartup<Startup>();
}).Build();

似乎构建应该在ConfigureWebHostDefaults内部完成,以使其工作,否则配置将被跳过,但如果我错了,请纠正我。

这个方法很有效:

var host = new WebHostBuilder()
.ConfigureServices(servicesCollection =>
{
var serviceProvider = servicesCollection.BuildServiceProvider();
IConfiguration configuration = (IConfiguration)serviceProvider.GetService(typeof(IConfiguration));
servicesCollection.AddSingleton<ISendEmailHandler>(new SendEmailHandler(configuration));
})
.UseStartup<Startup>()
.Build();

这也展示了如何从。net core (IConfiguration)中注入预定义的依赖项

你可能会错过这个:

services.AddScoped<IDependencyTwoThatIsDependentOnDependencyOne, DependencyTwoThatIsDependentOnDependencyOne>();

对我来说,在ConfigureServices中添加DB上下文是有效的,如下所示:

services.AddDBContext<DBContextVariable>();

我收到这个错误消息,ILogger实例注射到一个。net 5类。我需要添加类类型来修复它。

ILogger记录器>ILogger & lt; MyClass>记录器

如果您正在使用dotnet 5及以下版本,您还可以检查是否已经在服务中注册了存储库。

有同样的问题,我所做的只是在Startup.cs中注册我的DBContext。

问题是,您调用的是应用程序尚未注册的DBContext,因此当您的视图试图引用它时,它不知道该做什么。

错误信息的关键部分,"同时试图激活

 private readonly SmartPayDBContext _context;

这个方法对我很有效

    public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
            

services.AddDbContext<SmartPayDBContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
}

不确定这是否会帮助其他人,但我是正确的依赖注入,并在试图访问我的API控制器时得到这个错误。

我不得不关闭项目并在已经将它们添加到我的startup.cs类后重新构建——出于某种原因,重新构建让Visual Studio在出现错误之前就识别出服务类是正确注册的。

为修复添加另一个答案,因为我已经被这个问题咬了很多次了。如果你创建了一个“选项”;类,你绑定到配置,你可能像这样注册它:

// Your options class
public record MyOptions(string SomeSetting);


// ----- 8< -----


public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.Configure<MyOptions>(configuration.GetSection(configPath));
}
}

如果你现在有了这些选项的消费者,你会发现下面的代码会抛出上面的异常:

public class OptionsConsumer
{
public OptionsConsumer(MyOptions options)
{
}
}

你必须要“包装好的”;选择的版本:

public class OptionsConsumer
{
public OptionsConsumer(IOptions<MyOptions> options)
{
}
}