Мне интересно узнать больше о том, как люди внедряют регистрацию с помощью платформ инъекций зависимостей. Хотя ссылки ниже и мои примеры относятся к log4net и Unity, я не обязательно буду использовать их. Для инъекций зависимостей /IOC я, вероятно, буду использовать MEF, поскольку это стандарт, на котором останавливается остальная часть проекта (большая).
Я очень новичок в инъекции зависимости /ioc и довольно новичок в С# и .NET(написал очень небольшой производственный код в С#/.NET после 10 лет или около того VC6 и VB6). Я провел много исследований по различным решениям для ведения журналов, которые есть там, поэтому я считаю, что у меня есть приличная ручка для их наборов функций. Я просто недостаточно знаком с реальной механикой получения одной зависимой инъекции (или, может быть, более "правильной" ), получая абстрагированную версию одной зависимой инъекции).
Я видел другие сообщения, связанные с регистрацией и/или зависимостью, например: интерфейсы вложения и протоколирования зависимостей
Как выглядит класс Wrapper Log4Net?
снова о конфигурации log4net и Unity IOC
Мой вопрос не имеет особого отношения к "Как мне внедрить платформу регистрации xxx с помощью инструмента ioc yyy?" Скорее, меня интересует, как люди обрабатывали завершение платформы регистрации (как часто, но не всегда рекомендуется) и конфигурации (то есть app.config). Например, используя log4net в качестве примера, я мог бы настроить (в app.config) несколько регистраторов, а затем получить эти регистраторы (без инъекции зависимостей) стандартным способом использования кода следующим образом:
private static readonly ILog logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
В качестве альтернативы, если мой регистратор не назван для класса, а скорее для функциональной области, я мог бы сделать это:
private static readonly ILog logger = LogManager.GetLogger("Login");
private static readonly ILog logger = LogManager.GetLogger("Query");
private static readonly ILog logger = LogManager.GetLogger("Report");
Итак, я думаю, что мои "требования" будут примерно такими:
-
Я хотел бы изолировать источник моего продукта от прямой зависимости от платформы регистрации.
-
Я хотел бы иметь возможность разрешить конкретный экземпляр именованного экземпляра журнала (возможно, совместно использовать один и тот же экземпляр среди всех запросов одного и того же именованного экземпляра) прямо или косвенно с помощью какой-либо инъекции зависимостей, возможно, с помощью MEF.
-
Я не знаю, буду ли я называть это жестким требованием, но мне нужна возможность получить именованный логгер (отличный от регистратора классов) по требованию. Например, я могу создать регистратор для моего класса на основе имени класса, но один метод требует особой тяжелой диагностики, которую я бы хотел контролировать отдельно. Другими словами, мне может потребоваться, чтобы один класс "зависел" от двух отдельных экземпляров журнала.
Давайте начнем с номера 1. Я прочитал ряд статей, прежде всего здесь, в stackoverflow, о том, стоит ли обертывать идею. См. Ссылку "Лучшие практики" выше и перейдите к jeffrey hantin за один взгляд на то, почему плохо переносить log4net. Если вы сделали обертку (и если бы вы могли обернуть ее эффективно), вы бы привязались строго для цели инъекции/удаления прямой зависимости? Или вы также попытаетесь отвлечь часть или всю информацию о log4net app.config?
Предположим, что я хочу использовать System.Diagnostics, я бы, вероятно, захотел внедрить логику на основе интерфейса (возможно, даже используя "общий" интерфейс ILogger/ILog), возможно, основанный на TraceSource, чтобы я мог его вводить. Внесите ли вы интерфейс, скажем, через TraceSource, и просто используйте информацию о приложении. System.infigostics.config как??
Что-то вроде этого:
public class MyLogger : ILogger
{
private TraceSource ts;
public MyLogger(string name)
{
ts = new TraceSource(name);
}
public void ILogger.Log(string msg)
{
ts.TraceEvent(msg);
}
}
И используйте его следующим образом:
private static readonly ILogger logger = new MyLogger("stackoverflow");
logger.Info("Hello world!")
Перемещение по номеру 2... Как разрешить конкретный экземпляр именного журнала? Должен ли я просто использовать информацию app.config для платформы регистрации, которую я выбираю (т.е. Разрешить регистраторы на основе схемы именования в app.config)? Итак, в случае log4net, возможно, я предпочитаю "вводить" LogManager (обратите внимание, что я знаю, что это невозможно, поскольку это статический объект)? Я мог бы обернуть LogManager (назовите его MyLogManager), дать ему интерфейс ILogManager, а затем разрешить интерфейс MyLogManager.ILogManager. Мои другие объекты могут иметь зависимость (Import in MEF parlance) от ILogManager (Экспорт из сборки, где она реализована). Теперь у меня могут быть такие объекты:
public class MyClass
{
private ILogger logger;
public MyClass([Import(typeof(ILogManager))] logManager)
{
logger = logManager.GetLogger("MyClass");
}
}
Когда вызывается ILogManager, он будет напрямую делегировать log8net LogManager. В качестве альтернативы, может ли обернутый LogManager взять экземпляры ILogger, которые он получает, на основе app.config и добавить их в контейнер (??) MEF по имени. Позже, когда запрашивается логгер с тем же именем, для этого имени запрашивается обернутый LogManager. Если там находится ILogger, это разрешается именно так. Если это возможно с помощью MEF, есть ли какие-либо выгоды для этого?
В этом случае, действительно, только ILogManager "инъецируется", и он может выдавать экземпляры ILogger так, как это обычно делает log4net. Как этот тип инъекций (по существу из factory) сравнивается с введением именованных экземпляров журнала? Это позволяет более легко использовать файл app.config для log4net (или другой платформы регистрации).
Я знаю, что я могу получить именованные экземпляры из контейнера MEF следующим образом:
var container = new CompositionContainer(<catalogs and other stuff>);
ILogger logger = container.GetExportedValue<ILogger>("ThisLogger");
Но как мне получить именованные экземпляры в контейнер? Я знаю об основанной на атрибутах модели, где у меня могут быть разные реализации ILogger, каждый из которых называется (через атрибут MEF), но это на самом деле не помогает мне. Есть ли способ создать что-то вроде app.config(или раздела в нем), который будет перечислять регистраторы (все одинаковые реализации) по имени и что MEF может читать? Может ли/должен быть центральный "менеджер" (например, MyLogManager), который разрешает имена журналов через базовый app.config, а затем вставляет разрешенный регистратор в контейнер MEF? Таким образом, он будет доступен кому-то другому, имеющему доступ к одному и тому же контейнеру MEF (хотя без знания MyLogManager о том, как использовать информацию log4net app.config, кажется, что контейнер не сможет напрямую разрешить любые именованные журналы).
Это уже довольно долгое время. Надеюсь, это будет согласованным. Не стесняйтесь делиться какой-либо конкретной информацией о том, как вы зависите, внедряете платформу регистрации (мы, скорее всего, рассматриваем log4net, NLog или что-то (надеюсь, тонкое), основанное на System.Diagnostics) в вашем приложении.
Вы вводили "менеджер" и возвращали ли он экземпляры журнала?
Добавили ли вы свою собственную конфигурационную информацию в свой собственный раздел конфигурации или в свою конфигурационную конфигурацию платформы DI, чтобы упростить/возможно непосредственно импортировать экземпляры регистратора (т.е. сделать ваши зависимости на ILogger, а не на ILogManager).
Как насчет наличия статического или глобального контейнера, который имеет в нем интерфейс ILogManager или набор именованных экземпляров ILogger. Таким образом, вместо того, чтобы вводить в обычном смысле (через конструктор, свойство или данные участника), зависимость от протоколирования явно разрешается по требованию. Это хороший или плохой способ инъекции зависимости.
Я отмечаю это как сообщество wiki, так как это не похоже на вопрос с определенным ответом. Если кто-то чувствует себя иначе, не стесняйтесь его менять.
Спасибо за любую помощь!