c# - AspNetCore - 无法解析类型 X 的服务
问题描述
启动我的 Asp .Net Core Mvc Web 应用程序时出现此错误:
“某些服务无法构建(验证服务描述符时出错'ServiceType: Vepo.Application.IAddVeganItemToAppUseCase Lifetime: Transient ImplementationType: Vepo.Application.AddVeganItemToAppUseCase': Unable to resolve service for type 'Vepo.Data.GroceryItemGroceryStoresRepository' while试图激活“Vepo.Application.AddVeganItemToAppUseCase”。)”
所以看起来这部分是罪犯:
无法解析“Vepo.Data.GroceryItemGroceryStoresRepository”类型的服务。
在我的 Startup.cs 我有这个:
services.AddScoped(typeof(IGroceryItemGroceryStoresRepository), typeof(GroceryItemGroceryStoresRepository));
services.AddTransient<IAddVeganItemToAppUseCase, AddVeganItemToAppUseCase>();
有什么问题吗?
以下是所有相关代码:
IRepository.cs
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace Vepo.Data
{
public interface IRepository<EntityType, IdType>
{
Task<EntityType> Save(EntityType entity);
EntityType Fetch(IdType id);
IEnumerable<EntityType> FetchAll();
bool EntityExists(IdType id);
}
}
ARepository.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Vepo.Common.Utilities;
using Vepo.DataContext;
using Vepo.Domain;
namespace Vepo.Data
{
[Serializable]
public abstract class ARepository<EntityType, IdType> : IRepository<EntityType, IdType> where EntityType : ADomainEntity<IdType>
{
protected readonly VepoContext context;
protected DbSet<EntityType> entities;
protected string errorMessage = string.Empty;
public ARepository(VepoContext context)
{
this.context = context;
entities = context.Set<EntityType>();
}
public bool Compare<T>(T x, T y)
{
return EqualityComparer<T>.Default.Equals(x, y);
}
public virtual async Task<EntityType> Save(EntityType entity)
{
if (entity == null)
{
throw new ArgumentNullException("entity");
}
if (NumberUtilities.IsNumber(entity.Id))
{
if (Convert.ToInt32(entity.Id) > 0)
{
await context.SaveChangesAsync();
} else {
await entities.AddAsync(entity);
await context.SaveChangesAsync();
}
}
return entity;
}
public EntityType Fetch(IdType id)
{
return entities.SingleOrDefault(s => Compare<IdType>(s.Id, id));
}
public IEnumerable<EntityType> FetchAll()
{
return entities.AsEnumerable();
}
public void Delete(EntityType entity)
{
if (entity == null)
{
throw new ArgumentNullException("entity");
}
entities.Remove(entity);
context.SaveChanges();
}
public void Remove(EntityType entity)
{
if (entity == null)
{
throw new ArgumentNullException("entity");
}
entities.Remove(entity);
}
public void SaveChanges()
{
context.SaveChanges();
}
public virtual bool EntityExists(IdType id)
{
return entities.Any(e => Compare<IdType>(e.Id, id));
}
}
}
IGroceryItemGroceryStoresRepository.cs:
using Vepo.Domain;
namespace Vepo.Data
{
public interface IGroceryItemGroceryStoresRepository : IRepository<GroceryItemGroceryStore, int>
{
}
}
GroceryItemGroceryStoresRepository.cs
using System;
using Microsoft.EntityFrameworkCore;
using Vepo.DataContext;
using Vepo.Domain;
using System.Linq;
using System.Threading.Tasks;
namespace Vepo.Data
{
public class GroceryItemGroceryStoresRepository : ARepository<GroceryItemGroceryStore, int>, IGroceryItemGroceryStoresRepository
{
public GroceryItemGroceryStoresRepository(VepoContext context) : base(context)
{
}
public override bool EntityExists(int id)
{
return context.GroceryItemGroceryStores.Any(e => e.VeganItemId == id);
}
public async override Task<GroceryItemGroceryStore> Save(GroceryItemGroceryStore entity)
{
++entity.VeganItem.CurrentRevisionId;
var toReturnVeganItem = entity.VeganItem;
var toReturnEstablishment = entity.Establishment;
context.GroceryItems.Add(entity.VeganItem);
context.SaveChanges();
context.Set<GroceryStore>().AddIfNotExists(entity.Establishment , x => x.PlaceId == entity.Establishment.PlaceId);
context.SaveChanges();
var establishmentId = context.GroceryStores.Single(a => a.PlaceId == entity.Establishment.PlaceId).Id;
var veganItemId = context.GroceryItems.Single(a => a.Brand == entity.VeganItem.Brand && a.Name == entity.VeganItem.Name).Id;
toReturnEstablishment.Id = establishmentId;
toReturnVeganItem.Id = veganItemId;
entity.VeganItemId = veganItemId;
entity.EstablishmentId = establishmentId;
entity.VeganItem = null;
entity.Establishment = null;
context.Set<GroceryItemGroceryStore>().AddIfNotExists(entity , x => x.VeganItemId == veganItemId && x.EstablishmentId == establishmentId);
try
{
await context.SaveChangesAsync();
}
catch (DbUpdateException)
{
if (EntityExists(entity.VeganItemId))
{
throw;
}
else
{
throw;
}
}
entity.VeganItem = toReturnVeganItem;
entity.Establishment = toReturnEstablishment;
return entity;
}
}
}
IAddVeganItemToAppUseCase.cs
using System.Threading.Tasks;
using Vepo.Domain;
namespace Vepo.Application
{
public interface IAddVeganItemToAppUseCase
{
Task<GroceryItemGroceryStore> Invoke(GroceryItemGroceryStore entity);
}
}
AddVeganItemToAppUseCase.cs
using System.Threading.Tasks;
using Vepo.Data;
using Vepo.Domain;
namespace Vepo.Application
{
public class AddVeganItemToAppUseCase : IAddVeganItemToAppUseCase
{
private GroceryItemGroceryStoresRepository repository;
public AddVeganItemToAppUseCase(GroceryItemGroceryStoresRepository repository)
{
this.repository = repository;
}
public Task<GroceryItemGroceryStore> Invoke(GroceryItemGroceryStore entity)
{
return repository.Save(entity);
}
}
}
启动.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.EntityFrameworkCore;
using System.Text.Json.Serialization;
using Vepo.Domain;
using Vepo.DataContext;
using System;
using Vepo.Data;
using Vepo.Application;
namespace Vepo.Web
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services
.AddDbContext<VepoContext>(opt =>
opt
.UseNpgsql(
Configuration
.GetConnectionString("DefaultConnection"))
.EnableSensitiveDataLogging()
.EnableDetailedErrors()
.LogTo(Console.WriteLine));
services.AddControllers().AddJsonOptions(opt =>
{
opt.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
});
services.AddControllers().AddNewtonsoftJson(x => x.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);
services.AddMvc().AddJsonOptions(options =>
{
options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.Preserve;
});
services.AddScoped(typeof(IGroceryItemGroceryStoresRepository), typeof(GroceryItemGroceryStoresRepository));
services.AddTransient<IAddVeganItemToAppUseCase, AddVeganItemToAppUseCase>();
services.AddSwaggerGen();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My Test1 Api v1");
});
}
}
}
解决方案
您正在注册GroceryItemGroceryStoresRepository
为 type 的接口IGroceryItemGroceryStoresRepository
,但是您GroceryItemGroceryStoresRepository
在AddVeganItemToAppUseCase
. 将您的构造函数中的注入对象AddVeganItemToAppUseCase
从具体类型更改为相应的接口注册,它应该可以工作。
public class AddVeganItemToAppUseCase : IAddVeganItemToAppUseCase
{
private IGroceryItemGroceryStoresRepository repository;
public AddVeganItemToAppUseCase(IGroceryItemGroceryStoresRepository repository)
{
this.repository = repository;
}
public Task<GroceryItemGroceryStore> Invoke(GroceryItemGroceryStore entity)
{
return repository.Save(entity);
}
}
推荐阅读
- wordpress - Wordpress API - 访问页面字段
- c++ - 自动转换为无效未使用的变量 C++
- android - 将 CSV 文件从 Android 设备传输到 PC
- android - 当我更新 ListView 上的列表时,Flutter 页面不会重新加载
- java - Intellij java.lang.NoSuchFieldError 更新后启动
- google-cloud-platform - 将 Google Cloud Bucket 下载到本地计算机上的特定文件夹
- git - `ls-remote --refs` 与克隆然后 `describe --tags` 有什么关系?
- plugins - Terraform 与插件不兼容的 API 版本。插件版本:5,核心版本:4
- powershell - 从另一个脚本运行 PowerShell 脚本,传递字符串变量
- azure-databricks - 我可以在不使用管道的情况下从 Azure Synapse 查询 SQL Server 数据库吗?