为啥我的通用服务出现“无法实例化实现类型”错误?
Posted
技术标签:
【中文标题】为啥我的通用服务出现“无法实例化实现类型”错误?【英文标题】:Why am I getting the error "Cannot instantiate implementation type" for my generic service?为什么我的通用服务出现“无法实例化实现类型”错误? 【发布时间】:2017-08-16 16:57:37 【问题描述】:我有一个通用存储库,我已经在我的 WEB API 控制器中实例化了一段时间没有问题。
这是我的控制器过去的样子:
[Route("api/[controller]")]
public class EmployeesController : Controller
private IGenericRepository<Employee> _empRepo;
public EmployeesController(IGenericRepository<Employee> employeeRepo)
_empRepo = employeeRepo;
// GET: api/employees
[HttpGet]
public async Task<IEnumerable<Employee>> GetEmployeesAsync(
string firstName = null, string lastName = null)
//return await _empRepo.GetAll().Include("Organization").Include("PayPlan").Include("GradeRank").Include("PositionTitle").Include("Series").Include("BargainingUnit")
// .Where(e => (string.IsNullOrEmpty(firstName) || e.FirstName.Contains(firstName))
// && (string.IsNullOrEmpty(lastName) || e.LastName.Contains(lastName))
// )
// .ToListAsync();
return await _empRepo.GetAllIncluding(
a => a.Organization,
b => b.PayPlan,
c => c.GradeRank,
d => d.PositionTitle,
e => e.Series,
f => f.BargainingUnit)
.Where(e => (string.IsNullOrEmpty(firstName) || e.FirstName.Contains(firstName))
&& (string.IsNullOrEmpty(lastName) || e.LastName.Contains(lastName))
)
.ToListAsync();
// GET api/employees/5
[HttpGet("id", Name = "GetEmployeeById")]
public async Task<IActionResult> GetEmployeeByIdAsync(long id)
//var employee = await _empRepo.Find(id).Include("Organization").Include("PayPlan").Include("GradeRank").Include("PositionTitle").Include("Series").Include("BargainingUnit").SingleAsync();
var employee = await _empRepo.GetSingleIncludingAsync(id,
a => a.Organization,
b => b.PayPlan,
c => c.GradeRank,
d => d.PositionTitle,
e => e.Series,
f => f.BargainingUnit);
if (employee == null)
return NotFound();
else
return new ObjectResult(employee);
// PUT api/employees/id
[HttpPut("id")]
public async Task<IActionResult> PutEmployeeAsync([FromBody] Employee emp)
var employee = await _empRepo.UpdateAsync(emp);
if (employee == null)
return NotFound();
await _empRepo.SaveAsync();
return new ObjectResult(employee);
我们会像这样在 StartUp 中配置 DI:
services.AddScoped(typeof(IGenericRepository<>), typeof(GenericRepository<>));
现在我刚刚重构并尝试在控制器和通用存储库之间放置一个服务层。
这是我在 StartUp 中的第二条 DI 线:
services.AddScoped(typeof(IGenericService<>), typeof(IGenericService<>));
所以现在我有这两条 DI 线:
services.AddScoped(typeof(IGenericRepository<>), typeof(GenericRepository<>));
services.AddScoped(typeof(IGenericService<>), typeof(IGenericService<>));
以下是我当前的代码:
从通用回购开始:
public enum FilteredSource
All,
GetAllIncluding,
public class GenericRepository<T> : IGenericRepository<T>
where T: BaseEntity
protected readonly ApplicationDbContext _context;
protected DbSet<T> _dbSet;
public GenericRepository(ApplicationDbContext context)
_context = context;
_dbSet = context.Set<T>();
// no eager loading
private IQueryable<T> All => _dbSet.Cast<T>();
#region FIXME : DELETE
// FIXME: Delete and use ALL instead.
public IQueryable<T> GetAll() => _dbSet.AsQueryable();
// FIXME: Delete and use GetSingleIncludingAsync instead.
public IQueryable<T> Find(long id) =>
_dbSet.Where(e => e.Id == id).AsQueryable();
#endregion
// eager loading
private IQueryable<T> GetAllIncluding(
params Expression<Func<T, object>>[] includeProperties) =>
includeProperties.Aggregate(All, (currentEntity, includeProperty) => currentEntity.Include(includeProperty));
// no eager loading
public async Task<T> GetSingleIncludingAsync(long id)
return await _dbSet.SingleOrDefaultAsync(e => e.Id == id);
/// <summary>
/// Takes in a lambda selector and let's you filter results from GetAllIncluding and All.
/// </summary>
/// <param name="selector">labmda expression to filter results by.</param>
/// <param name="getFilteredSource">All or GetAllIncluding as the method to get results from.</param>
/// <param name="includeProperties">array of eager load lamda expressions.</param>
/// <returns></returns>
public async Task<IEnumerable<T>> GetFiltered(
Expression<Func<T, bool>> selector, FilteredSource filteredSource,
Expression<Func<T, object>>[] includeProperties = null)
var results = default(IEnumerable<T>);
switch (filteredSource)
case FilteredSource.All:
results = All.Where(selector);
break;
case FilteredSource.GetAllIncluding:
results = GetAllIncluding(includeProperties).Where(selector);
break;
return await results.AsQueryable().ToListAsync();
// eager loading
public async Task<T> GetSingleIncludingAsync(
long id, params Expression<Func<T, object>>[] includeProperties)
IQueryable<T> entities = GetAllIncluding(includeProperties);
//return await Filter<long>(entities, x => x.Id, id).FirstOrDefaultAsync();
return await entities.SingleOrDefaultAsync(e => e.Id == id);
public async Task<T> InsertAsync(T entity)
if (entity == null)
throw new ArgumentNullException($"No nameof(T) Entity was provided for Insert");
await _dbSet.AddAsync(entity);
return entity;
public async Task<T> UpdateAsync(T entity)
T entityToUpdate = await
_dbSet.AsNoTracking().SingleOrDefaultAsync(e => e.Id == entity.Id);
if (entityToUpdate == null)
//return null;
throw new ArgumentNullException($"No nameof(T) Entity was provided for Update");
_dbSet.Update(entity);
return entity;
public async Task<T> DeleteAsync(T entity)
_dbSet.Remove(entity);
return await Task.FromResult(entity);
public Task SaveAsync() => _context.SaveChangesAsync();
接口定义:
public interface IGenericRepository<T>
where T : BaseEntity
#region FIXME : DELETE
// FIXME: Delete and use ALL instead.
IQueryable<T> GetAll();
// FIXME: Delete and use GetSingleIncludingAsync instead.
IQueryable<T> Find(long id);
#endregion
// eager loading
Task<T> GetSingleIncludingAsync(
long id, params Expression<Func<T, object>>[] includeProperties);
Task<IEnumerable<T>> GetFiltered(
Expression<Func<T, bool>> selector, FilteredSource filteredSource,
Expression<Func<T, object>>[] includeProperties = null);
Task<T> InsertAsync(T entity);
Task<T> UpdateAsync(T entity);
Task<T> DeleteAsync(T entity);
#region Possible TODOs:
//Task<IEnumerable<T>> FindBy(Expression<Func<T, bool>> predicate);
//Task AddRange(IEnumerable<T> entities);
//Task RemoveRange(IEnumerable<T> entities);
#endregion
Task SaveAsync();
这被注入到我的通用服务中:
public class GenericService<T> : IGenericService<T>
where T : BaseEntity
private IGenericRepository<T> _genericRepo;
public GenericService(IGenericRepository<T> genericRepo)
_genericRepo = genericRepo;
public async Task<IEnumerable<T>> GetFiltered(
Expression<Func<T, bool>> selector, FilteredSource filteredSource,
Expression<Func<T, object>>[] includeProperties = null)
return await _genericRepo.GetFiltered(selector, filteredSource,
includeProperties);
// eager loading
public async Task<T> GetSingleIncludingAsync(long id, params Expression<Func<T, object>>[] includeProperties)
IEnumerable<T> entities = await _genericRepo.GetFiltered(null, FilteredSource.GetAllIncluding, includeProperties);
//return await Filter<long>(entities, x => x.Id, id).FirstOrDefaultAsync();
return entities.SingleOrDefault(e => e.Id == id);
public async Task<T> InsertAsync(T entity)
var result = await _genericRepo.InsertAsync(entity);
await _genericRepo.SaveAsync();
return entity;
public async Task<T> UpdateAsync(T entity)
var result = await _genericRepo.UpdateAsync(entity);
if (result != null)
await _genericRepo.SaveAsync();
return result;
public async Task<T> DeleteAsync(T entity)
throw new NotImplementedException();
服务的接口定义:
public interface IGenericService<T>
where T : BaseEntity
Task<IEnumerable<T>> GetFiltered(
Expression<Func<T, bool>> selector, FilteredSource filteredSource,
Expression<Func<T, object>>[] includeProperties = null);
// eager loading
Task<T> GetSingleIncludingAsync(long id, params Expression<Func<T, object>>[] includeProperties);
Task<T> InsertAsync(T entity);
Task<T> UpdateAsync(T entity);
Task<T> DeleteAsync(T entity);
最后,这是控制器:
[Route("api/[controller]")]
public class EmployeesController : Controller
private IGenericService<Employee> _genericService;
public EmployeesController(IGenericService<Employee> genericService)
_genericService = genericService;
// GET: api/employees
[HttpGet]
public async Task<IEnumerable<Employee>> GetEmployeesAsync(
string firstName = null, string lastName = null)
return await _genericService.GetFiltered(
e => (string.IsNullOrEmpty(firstName) || e.FirstName.Contains(firstName))
&& (string.IsNullOrEmpty(lastName) || e.LastName.Contains(lastName)),
FilteredSource.GetAllIncluding,
new Expression<Func<Employee, object>>[] a => a.Organization,
b => b.PayPlan,
c => c.GradeRank,
d => d.PositionTitle,
e => e.Series,
f => f.BargainingUnit
);
// GET api/employees/5
[HttpGet("id", Name = "GetEmployeeById")]
public async Task<IActionResult> GetEmployeeByIdAsync(long id)
//var employee = await _empRepo.Find(id).Include("Organization").Include("PayPlan").Include("GradeRank").Include("PositionTitle").Include("Series").Include("BargainingUnit").SingleAsync();
var employee = await _genericService.GetSingleIncludingAsync(id,
a => a.Organization,
b => b.PayPlan,
c => c.GradeRank,
d => d.PositionTitle,
e => e.Series,
f => f.BargainingUnit);
if (employee == null)
return NotFound();
else
return new ObjectResult(employee);
// PUT api/employees/id
[HttpPut("id")]
public async Task<IActionResult> PutEmployeeAsync([FromBody] Employee emp)
var employee = await _genericService.UpdateAsync(emp);
if (employee == null)
return NotFound();
return new ObjectResult(employee);
我只是不确定如何插入中间服务层。
【问题讨论】:
【参考方案1】:根据大卫的回答,我不得不在我的服务实现类中删除“抽象”。不过,我在课堂上也有一些抽象方法和属性。因此,在将它们设为非抽象并创建 公共构造函数之后,我就能够注册服务了。
【讨论】:
【参考方案2】:根据 Bartosz 的回答,出现此消息的另一个原因是,如果您尝试使用像这样的通用具体类型来满足非通用接口:
services.AddScoped(typeof(IMyDependency), typeof(MyDependency<,>));
这不起作用,因为 DI 容器不知道在实例化 MyDependency 时要提供什么通用参数。要么接口必须转换为泛型,要么你需要一个工厂来手动实例化它。
【讨论】:
【参考方案3】:到目前为止,很好的问题和很好的答案......
如果你的问题不同但错误信息相同
...您正在为默认实现注册服务,未指定实现类型,如下所示:
services.AddScoped<IMyDependency>();
那么这个错误是没有用的,因为它没有详细说明为什么事情不起作用:
无法为服务类型“MyApp.IMyDependency”实例化实现类型“MyApp.IMyDependency”。
在这种情况下,将服务注册更改为:
services.AddScoped<IMyDependency, MyDependency>();
这将改善错误消息,并告诉您问题出在哪里,如下所示:
无法构造某些服务(验证服务描述符“ServiceType: MyApp.IMyDependency Lifetime: Transient ImplementationType: MyApp.MyDependency”时出错:无法解析“MyApp.ILowerDependency”类型的服务 在尝试激活“MyApp.IMyDependency”时。)
在默认的 ASP.NET 核心 DI 容器中,需要显式注册整个依赖关系图(可能除了 ILogger 等一些异常)
【讨论】:
【参考方案4】:这件事最近发生在我身上。我将实现类标记为“抽象”,这是早期设计的产物。我删除了它,容器能够毫无问题地实例化该类。
【讨论】:
【参考方案5】:当 service 类没有从 IService 继承时发生在我身上 界面
【讨论】:
【参考方案6】:我是个白痴。 我有实现的接口。 我改变了:
services.AddScoped(typeof(IGenericService<>), typeof(IGenericService<>));
到
services.AddScoped(typeof(IGenericService<>), typeof(GenericService<>));
【讨论】:
同样的错误。我正在使用别名并认为导致错误,例如using shortName= Foo.Repository.Repositories.Contacts;
这其实很好,问题是混淆了接口/实现顺序。
我添加了一个抽象实现类。这个错误怎么这么流行以上是关于为啥我的通用服务出现“无法实例化实现类型”错误?的主要内容,如果未能解决你的问题,请参考以下文章
为啥我的 Java appengine 应用程序在 5 年后没有任何问题出现“500 服务器错误”?
为啥我将网站放在 debian 服务器上时出现 cayenne 连接错误