What would be the most efficient way to instanciate an object according to a generic type passed to a Factory class, for instance:
public class LoggerFactory
{
public static ILogger<T> Create<T>()
{
// Switch Statement?
// Generic Dictionary?
// EX.: if "T" is of type "string": return (ILogger<T>)new StringLogger();
}
}
How would you do it? Which branching statement? etc...
I think it's best to keep it simple, perhaps something like this:
public static class LoggerFactory
{
static readonly Dictionary<Type, Type> loggers = new Dictionary<Type, Type>();
public static void AddLoggerProvider<T, TLogger>() where TLogger : ILogger<T>, new()
{
loggers.Add(typeof(T), typeof(TLogger));
}
public static ILogger<T> CreateLogger<T>()
{
//implement some error checking here
Type tLogger = loggers[typeof(T)];
ILogger<T> logger = (ILogger<T>) Activator.CreateInstance(tLogger);
return logger;
}
}
You just call the AddLoggerProvider
for each type you want to support, can be extended at runtime, it ensures you definetly add an implementation of the interface to the library and not some object, isn't very fast because of the Activator
, but creating a logger wont likely be a bottleneck anyway. Hope it looks okay.
Usage:
// initialize somewhere
LoggerFactory.AddLoggerProvider<String, StringLogger>();
LoggerFactory.AddLoggerProvider<Exception, ExceptionLogger>();
// etc..
ILogger<string> stringLogger = LoggerFactory.CreateLogger<string>();
Note: each ILogger<T>
requires a parameterless constructor for the Activator
, but that too is ensured with the new()
generic constraint in the add method.
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