簡體   English   中英

泛型類的依賴注入

[英]Dependency injection for generic class

我有一個通用類和一個通用接口,如下所示:

public interface IDataService<T> where T: class
{
    IEnumerable<T> GetAll();
}

public class DataService<T> : IDataService<T> where T : class
{
    public IEnumerable<T> GetAll()
    {
        return Seed<T>.Initialize();
    }
}

public static IEnumerable<T> Initialize()
{
    List<T> allCalls = new List<T>();
    ....
    return allCalls;
}

現在在我的 StartUp.cs 中,我正在連接類和接口

public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient(typeof(IDataService<>), typeof(DataService<>));
    ...
}

當我嘗試在我的例如 Repository.cs 中使用它時,它始終為空。

public class Repository<T> : IRepository<T> where T : class
{
    private readonly IDataService<T> _dataService;

    public Repository(IDataService<T> dataService)
    {
        _dataService = dataService;
    ...
    }
    ...
}

編輯這是請求的存儲庫接口和類

public interface IRepository<T> where T : class
{
    double GetCallPrice(T callEntity, Enum billingType);
    double GetCallPriceFromIdAndBillingType(int id, Enum billingType);
}

和 Repository.cs 類

public class Repository<T> : IRepository<T> where T : class
{
    private readonly IDataService<T> _dataService;
    private IEnumerable<T> _allCalls;

    public Repository(IDataService<T> dataService)
    {
        _dataService = dataService;
    }

    public double GetCallPrice(int id)
    {
        _allCalls = _dataService.GetAllCalls();
        ...
    }
    ...
}
services.AddTransient(typeof(IDataService<>), typeof(DataService<>));

理想情況下,這不應該被允許,但由於方法接受類型作為參數,它在沒有執行任何驗證的情況下接受了它。 正如沒有人預料到的那樣,有人會嘗試使用它。

之所以為空,是因為typeof(IDataService<>) !== typeof(IDataService<SomeClass>)

您可以在https://dotnetfiddle.net/8g9Bx7查看示例

這就是原因,DI 解析器永遠不會知道如何解析。 大多數 DI 容器僅在類型實現請求的接口或將基類作為請求類時才解析類型。

任何 DI 容器都會為類型 B 解析類型 A,只有當 A 繼承 B 或 A 實現 B 時。

在您的情況下, DataService<>實現了IDataService<> ,但DataService<T>沒有實現IDataService<>

讓它工作的唯一方法是為每種數據類型調用相同的

services.AddTransient(typeof(IDataService<Customer>), typeof(DataService<Customer>));

services.AddTransient(typeof(IDataService<Order>), typeof(DataService<Order>));

services.AddTransient(typeof(IDataService<Message>), typeof(DataService<Message>));

您可以創建一個 ServiceFactory...

interface IDataServiceFactory{
     DataService<T> Get<T>();
}

class DataServiceFactory : IDataServiceFactory{
     public DataService<T> Get<T>(){
          //.. your own logic of creating DataService

          return new DataService<T>();
     }
}

並注冊

services.AddTransient(typeof(IDataServiceFactory), typeof(DataServiceFactory));

Microsoft 的 Logging 擴展在其服務集合配置中使用開放泛型

 services.TryAdd(ServiceDescriptor.Singleton(typeof(ILogger<>), typeof(Logger<>)));

該行允許將記錄器類的封閉版本注入為

public SomeService(ILogger<SomeService> logger)
{
    // ...

測試表明,對於共享服務范圍,每種不同類型的T將映射到不同的服務實例,並且可以請求的任何有效類型T

如果你想玩這個,使用這個測試平台: https : //dotnetfiddle.net/dVDqnj

這種方法假定行為不是為接口的特定實現定義的,而是更多的信息。 如果您需要IGeneric<Foo>IGeneric<Bar>不同實現, IGeneric<Foo>需要單獨定義每個實現服務。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM