I have a generic class and a generic interface like this:
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;
}
Now in my StartUp.cs I'm hooking up the class and interface
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient(typeof(IDataService<>), typeof(DataService<>));
...
}
When I try to use it in my e.g. Repository.cs its always null.
public class Repository<T> : IRepository<T> where T : class
{
private readonly IDataService<T> _dataService;
public Repository(IDataService<T> dataService)
{
_dataService = dataService;
...
}
...
}
EDIT Here is the requested Repository Interface and class
public interface IRepository<T> where T : class
{
double GetCallPrice(T callEntity, Enum billingType);
double GetCallPriceFromIdAndBillingType(int id, Enum billingType);
}
And the Repository.cs class
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<>));
Ideally this should not be allowed, but as method accepts type as parameter, it took it without performing any validation. As nobody expected anyone would try to use it.
The reason it is null, because typeof(IDataService<>) !== typeof(IDataService<SomeClass>)
You can check example at https://dotnetfiddle.net/8g9Bx7
That is the reason, DI resolver will never know how to resolve. Most DI containers resolve types only if type implements requested interface or has base class as requested class.
Any DI container will resolve type A for type B, only if A inherits B or A implements B.
In your case, DataService<>
implements IDataService<>
, but DataService<T>
does not implement IDataService<>
Only way you can make it work is by calling same for every data type
services.AddTransient(typeof(IDataService<Customer>), typeof(DataService<Customer>));
services.AddTransient(typeof(IDataService<Order>), typeof(DataService<Order>));
services.AddTransient(typeof(IDataService<Message>), typeof(DataService<Message>));
OR
You can create a 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>();
}
}
And register
services.AddTransient(typeof(IDataServiceFactory), typeof(DataServiceFactory));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With