依赖注入场景下继承接口无法访问扩展方法的解决方案咨询
解决方案
你的判断是对的,基类BaseEntityWebApiProvider中声明的_logicProvider是IBaseEntityLogicProvider<TEntity>类型,而非泛型参数TLogicProvider,因此无法直接访问子接口IAuthorLogicProvider的专属方法。以下是几种可行的解决方式:
方式一:修改基类字段类型为泛型参数TLogicProvider
直接调整基类中_logicProvider的类型,使其使用泛型参数TLogicProvider而非父接口类型,这样子类就能直接调用子接口的方法:
[ApiController] [Route("Api/V1/[controller]")] public abstract class BaseEntityWebApiProvider<TEntity, TLogicProvider> : ControllerBase where TEntity : BaseEntity where TLogicProvider : IBaseEntityLogicProvider<TEntity> { #region [ Fields ] protected readonly ILogger<BaseEntityWebApiProvider<TEntity, TLogicProvider>> _logger; // 将类型改为TLogicProvider protected readonly TLogicProvider _logicProvider; #endregion #region [ CTor ] public BaseEntityWebApiProvider(ILogger<BaseEntityWebApiProvider<TEntity, TLogicProvider>> logger, TLogicProvider logicProvider) { this._logger = logger; this._logicProvider = logicProvider; } #endregion }
修改后,AuthorController中的this._logicProvider.GetListByBookIdAsync(bookId)可直接正常编译调用,无需额外改动。
方式二:在子类中进行类型转换
若不想修改基类,可在子类中将_logicProvider强制转换为IAuthorLogicProvider类型后再调用方法:
[HttpGet(nameof(MethodUrl.GetListByBookId) + "/{BookId}")] public async Task<IActionResult> GetListByBookIdAsync(string bookId) { try { // 转换为具体的子接口类型 var authorLogicProvider = (IAuthorLogicProvider)this._logicProvider; var result = await authorLogicProvider.GetListByBookIdAsync(bookId); if (result == null || result.Count() <= 0) { return NotFound("Empty"); } return Ok(result); } catch (ArgumentNullException ex) { this._logger.LogError(ex.Message); return BadRequest(); } catch (Exception ex) { this._logger.LogError(ex.Message); return new StatusCodeResult(StatusCodes.Status500InternalServerError); } }
注意:此方式需确保注入的_logicProvider确实是IAuthorLogicProvider的实现类,否则会抛出InvalidCastException。
方式三:在基类中添加类型安全的转换属性
可在基类中封装一个类型转换的属性,避免子类重复编写转换逻辑:
[ApiController] [Route("Api/V1/[controller]")] public abstract class BaseEntityWebApiProvider<TEntity, TLogicProvider> : ControllerBase where TEntity : BaseEntity where TLogicProvider : IBaseEntityLogicProvider<TEntity> { #region [ Fields ] protected readonly ILogger<BaseEntityWebApiProvider<TEntity, TLogicProvider>> _logger; protected readonly IBaseEntityLogicProvider<TEntity> _logicProvider; #endregion // 添加类型转换属性 protected TLogicProvider TypedLogicProvider => (TLogicProvider)_logicProvider; #region [ CTor ] public BaseEntityWebApiProvider(ILogger<BaseEntityWebApiProvider<TEntity, TLogicProvider>> logger, TLogicProvider logicProvider) { this._logger = logger; this._logicProvider = logicProvider; } #endregion }
随后在子类中使用该属性调用方法:
var result = await this.TypedLogicProvider.GetListByBookIdAsync(bookId);
这种方式既保留了基类原有的_logicProvider字段,又能安全访问子接口方法,同时避免子类重复编写转换代码。
内容的提问来源于stack exchange,提问作者thanh n. van
相关产品推荐
相关产品推荐

