Я думаю, что лучше сохранить это простым, возможно, что-то вроде этого:
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;
}
}
Вы просто вызываете AddLoggerProvider
для каждого типа, который хотите поддерживать, может быть расширен во время выполнения, это гарантирует, что вы определенно добавляете реализацию интерфейса к библиотеке, а не какой-либо объект, не очень быстро из-за Activator
, но создание логгера, скорее всего, не будет узким местом в любом случае. Надеюсь, все выглядит хорошо.
Использование:
// initialize somewhere
LoggerFactory.AddLoggerProvider<String, StringLogger>();
LoggerFactory.AddLoggerProvider<Exception, ExceptionLogger>();
// etc..
ILogger<string> stringLogger = LoggerFactory.CreateLogger<string>();
Примечание: для каждого ILogger<T>
требуется конструктор без параметров для Activator
, но это также обеспечивается общим ограничением new()
в методе add.