tags:

views:

28

answers:

1

I want to define a handful of (ADO.NET) appenders in my library, but allow users of my library to configure the use of those appenders. Something like this seems to be what I want:

XmlConfigurator.Configure(appenderStream1);
XmlConfigurator.Configure(appenderStream2);
XmlConfigurator.Configure();

But that doesn't seem to work, in spite of the debug output containing messages like this:

Configuration update mode [Merge].

What is the right way to do this? Or, is there an alternative to asking users to duplicate large chunks of XML configuration?

Solution: Thanks to Stephan's suggestion, I was able to implement the following log initialization method. It first reads the .config section into an XmlDocument and then adds external appenders (which are in my case embedded resources) to the document, finally feeding the whole lot to log4net.

static readonly string[] AppenderConfigs =
{
    "Logging.EntryPointAppender.xml",
    "Logging.TracingAppender.xml",
    "Logging.MessagesAppender.xml",
};

public static void Initialize()
{
    // this first bit reads the log4net config in the application's config file
    var section = (XmlElement)ConfigurationManager.GetSection("log4net");
    if (section == null)
        return;
    XmlDocument xml = new XmlDocument();
    using (var xml_reader = new XmlNodeReader(section))
        xml.Load(xml_reader);

    // then we augment the above XML with the content of our embedded resources
    foreach (var appender_config in AppenderConfigs)
        using (var stream = EmbeddedResource.Open("My.Assembly", appender_config))
            AddToConfig(xml, stream);
    XmlConfigurator.Configure(xml.DocumentElement);
}

static void AddToConfig(XmlDocument config, Stream xmlStream)
{
    var fragment = config.CreateDocumentFragment();
    using (var reader = new StreamReader(xmlStream))
        fragment.InnerXml = reader.ReadToEnd();
    config.LastChild.AppendChild(fragment);
}
+1  A: 

I would do the following:

  • read all xml fragments
  • combine them yourself (with linq or whatever) to a valid log4net configuration "file" (in memory of course)
  • feed that to log4net
Stefan Egli
Bah, I forgot to return to this question after implementing your suggestion! I've editing the resulting code to appear in my OP. Thank you!
ladenedge
you are very welcome :-)
Stefan Egli