In ASP.NET Core, one of the things you can do with Microsoft\'s dependency injection framework is bind \"open generics\" (generic types unbound to a concrete type) like so:<
The net.core dependency does not allow you to provide a factory method when registering an open generic type, but you can work around this by providing a type that will implement the requested interface, but internally it will act as a factory. A factory in disguise:
services.AddSingleton(typeof(IMongoCollection<>), typeof(MongoCollectionFactory<>)); //this is the important part
services.AddSingleton(typeof(IRepository<>), typeof(Repository<>))
public class Repository : IRepository {
private readonly IMongoCollection _collection;
public Repository(IMongoCollection collection)
{
_collection = collection;
}
// .. rest of the implementation
}
//and this is important as well
public class MongoCollectionFactory : IMongoCollection {
private readonly _collection;
public RepositoryFactoryAdapter(IMongoDatabase database) {
// do the factory work here
_collection = database.GetCollection(typeof(T).Name.ToLowerInvariant())
}
public T Find(string id)
{
return collection.Find(id);
}
// ... etc. all the remaining members of the IMongoCollection,
// you can generate this easily with ReSharper, by running
// delegate implementation to a new field refactoring
}
When the container resolves the MongoCollectionFactory ti will know what type T is and will create the collection correctly. Then we take that created collection save it internally, and delegate all calls to it. ( We are mimicking this=factory.Create()
which is not allowed in csharp. :))
Update: As pointed out by Kristian Hellang the same pattern is used by ASP.NET Logging
public class Logger : ILogger
{
private readonly ILogger _logger;
public Logger(ILoggerFactory factory)
{
_logger = factory.CreateLogger(TypeNameHelper.GetTypeDisplayName(typeof(T)));
}
void ILogger.Log(...)
{
_logger.Log(logLevel, eventId, state, exception, formatter);
}
}
https://github.com/aspnet/Logging/blob/dev/src/Microsoft.Extensions.Logging.Abstractions/LoggerOfT.cs#L29
original discussion here:
https://twitter.com/khellang/status/839120286222012416