.Net Core DI 注入抽象 class 在派生 class 中使用接口

.Net Core DI injection Abstract class using Interface in a derived class

我有一个派生的 class 派生自抽象 class ,并且抽象 class 实现了接口。我想注入抽象 class 以使用来自抽象 class 和接口 class 的成员。我的 class 看起来像:

 public interface IStorageTableQueryHelper
{
    IStorageTableQueryHelper Connect(string storageconnectionString, string entityName);
    Task<ContinuationTokenPageResult<T>> ExecuteTableQueryAsyncStruct<T>(Expression<Func<TableEntity, bool>> expression,
        List<string> selectField) where T : struct;

    Task<ContinuationTokenPageResult<T>> ExecuteTableQueryAsyncStruct<T>(string query, List<string> selectField) where T : struct;
   
}

我的摘要class

 public abstract class StorageTableQueryAbstractHelper : IStorageTableQueryHelper
{
    public abstract IStorageTableQueryHelper Connect(string storageconnectionString, string entityName);

    public abstract Task<ContinuationTokenPageResult<T>> ExecuteTableQueryAsyncStruct<T>(
        Expression<Func<TableEntity, bool>> expression, List<string> selectField) where T : struct;


    public abstract Task<ContinuationTokenPageResult<T>> ExecuteTableQueryAsyncClass<T>(Expression<Func<TableEntity, bool>> expression, List<string> selectField) where T : class, new();

    public abstract Task<ContinuationTokenPageResult<T>> ExecuteTableQueryAsyncStruct<T>(string query,
        List<string> selectField) where T : struct;

    public abstract Task<ContinuationTokenPageResult<T>> ExecuteTableQueryAsyncClass<T>(string query,
        List<string> selectField) where T : class, new();

}

我的派生class

 public class StorageTableQueryHelper : StorageTableQueryAbstractHelper
{
    private readonly ITableService _tableService;
    private string connectionString { get; set; }
    private string entityName { get; set; }

    public StorageTableQueryHelper(ITableService tableService)
    {
        _tableService = tableService;
    }

    public override IStorageTableQueryHelper Connect(string storageConnectionString, string entityTableName)
    {
        this.connectionString = storageConnectionString;
        this.entityName = entityTableName;
        return this;
    }

    public override async  Task<ContinuationTokenPageResult<T>> ExecuteTableQueryAsyncStruct<T>(Expression<Func<TableEntity, bool>> expression, List<string> selectField) where T : struct
    {
       //var result= await _tableService.Connect(this.connectionString,this.entityName).ExecuteQuery<T>(expression, selectField);
       return null;
    }
    public override async Task<ContinuationTokenPageResult<T>> ExecuteTableQueryAsyncClass<T>(Expression<Func<TableEntity, bool>> expression, List<string> selectField) where T : class
    {
      //  var result = await _tableService.Connect(this.connectionString, this.entityName).ExecuteQuery<T>(expression, selectField);
        return null;
    }
    public override async Task<ContinuationTokenPageResult<T>> ExecuteTableQueryAsyncStruct<T>(string query, List<string> selectField) where T:struct
    {
        //var result = await _tableService.Connect(this.connectionString, this.entityName).ExecuteQuery<T>(query, selectField);
        return null;
    }
    public override async Task<ContinuationTokenPageResult<T>> ExecuteTableQueryAsyncClass<T>(string query, List<string> selectField) where T : class
    {
       // var result = await _tableService.Connect(this.connectionString, this.entityName).ExecuteQuery<T>(query, selectField);
        return null;
    }
}

还有class我想注入baseclass来使用接口实现

 public class EShopBusinessLogicProcessor : IEShopBusinessLogicProcessor
{
    private readonly IStorageTableQueryHelper _storageTableQueryHelper;
    private  EShopHttpRequestPayload _eShopHttpRequestPayload;

    public EShopBusinessLogicProcessor(IStorageTableQueryHelper storageTableQueryHelper)
    {
        _storageTableQueryHelper = storageTableQueryHelper;
    }

}

我正在尝试使用看起来像

的.Net Core DI
   services.AddScoped<IStorageTableQueryHelper, StorageTableQueryAbstractHelper>();
   services.AddScoped<StorageTableQueryHelper>();

但我无法注入它,因为它说接口不包含定义,即使我尝试使用抽象 class 注入

   public class EShopBusinessLogicProcessor : IEShopBusinessLogicProcessor
{
    private readonly StorageTableQueryAbstractHelper _storageTableQueryHelper;
    private  EShopHttpRequestPayload _eShopHttpRequestPayload;

    public EShopBusinessLogicProcessor(StorageTableQueryAbstractHelper storageTableQueryHelper)
    {
        _storageTableQueryHelper = storageTableQueryHelper;
    }

}

我如何实现将抽象 class 注入消费者 class?

您需要将具体 class 注册为 IStorageTableQueryHelper 实现,而不是抽象。

services.AddScoped<IStorageTableQueryHelper, StorageTableQueryHelper>();

DI 容器只会解析您注册的类型。它不会尝试查找其中一个已注册类型是否继承自另一个类型或是否实现了接口。如果有 2 或 3 个 class 实现该接口怎么办?

这就是为什么您不能只注册具体类型并注入它实现的接口的原因。

摘要class根本没有注册,所以无法解析。以下构造函数将始终失败:

public EShopBusinessLogicProcessor(StorageTableQueryAbstractHelper)

要完成这项工作,需要进行以下注册:

services.AddScoped<StorageTableQueryAbstractHelper, StorageTableQueryHelper>();

您可以使用回调注册接口并解析其中的抽象class。但是你必须首先将抽象class映射到一个实现。

// map the abstract class to an implementation
services.AddScoped<StorageTableQueryAbstractHelper, StorageTableQueryHelper>();

// then map the interface to abstract class
services.AddScoped<IStorageTableQueryHelper>(sp => sp.GetRequiredService<StorageTableQueryAbstractHelper>());

// or register it directly with the implementation
// services.AddScoped<IStorageTableQueryHelper, StorageTableQueryHelper>();