[英]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.