Index: src/Core/CompactRepositorySelector.cs =================================================================== --- src/Core/CompactRepositorySelector.cs (revision 675653) +++ src/Core/CompactRepositorySelector.cs (working copy) @@ -187,6 +187,8 @@ { // Must create the repository rep = CreateRepository(DefaultRepositoryName, repositoryType); + // set assembly + rep.Assembly = assembly; } return rep; Index: src/Core/DefaultRepositorySelector.cs =================================================================== --- src/Core/DefaultRepositorySelector.cs (revision 675653) +++ src/Core/DefaultRepositorySelector.cs (working copy) @@ -293,6 +293,8 @@ { // Create the repository rep = CreateRepository(actualRepositoryName, actualRepositoryType); + // set assembly + rep.Assembly = repositoryAssembly; if (readAssemblyAttributes) { Index: src/Layout/Pattern/AsmPatternConverter.cs =================================================================== --- src/Layout/Pattern/AsmPatternConverter.cs (revision 0) +++ src/Layout/Pattern/AsmPatternConverter.cs (revision 0) @@ -0,0 +1,182 @@ +#region Copyright & License +// +// Copyright 2001-2005 The Apache Software Foundation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#endregion + +using System.Reflection; +using System.IO; + +using log4net.Core; +using log4net.Util; + +namespace log4net.Layout.Pattern +{ + + /// + /// Write the assembly's description/title/version/trademark attributes to the output + /// + /// + /// + /// Writes the to the output writer. + /// + /// + /// Mark Mitchell + internal sealed class AsmPatternConverter : PatternLayoutConverter, IOptionHandler + { + /// + /// The constants below represent the options for this pattern converter + /// + /// %asm{Version} is assembly version + /// %asm{Description} is assembly description + /// %asm{Trademark} is assembly trademark + /// %asm{Title} is assembly title + /// + private const string VERSION = "Version"; + private const string DESCRIPTION = "Description"; + private const string TRADEMARK = "Trademark"; + private const string TITLE = "Title"; + + /// + /// Which assembly output type is this instance of AsmPatternConverter + /// + private AsmOutputType outputType = AsmOutputType.VERSION; + + /// + /// Available output types for AsmPatternConverter + /// + /// They correspond to the constant string above + /// + internal enum AsmOutputType + { + VERSION,DESCRIPTION,TRADEMARK,TITLE + } + + /// + /// Write the assembly's description/title/version/trademark attributes to the output + /// + /// that will receive the formatted result. + /// the event being logged + /// + /// + /// Writes the to the output . + /// + /// + override protected void Convert(TextWriter writer, LoggingEvent loggingEvent) + { + if (loggingEvent.Repository != null) + { + Assembly asm = loggingEvent.Repository.Assembly; + if (asm != null) + { + object[] attrs = null; + + switch (this.outputType) + { + case AsmOutputType.VERSION: + // AssemblyVersionAttribute returns null for whatever reason + // + // need to get the version the way below for it to work + writer.Write(asm.GetName().Version); + break; + case AsmOutputType.DESCRIPTION: + attrs = asm.GetCustomAttributes(typeof(AssemblyDescriptionAttribute), true); + if (attrs != null && attrs.Length == 1 && attrs[0] is AssemblyDescriptionAttribute) + { + AssemblyDescriptionAttribute desc = (AssemblyDescriptionAttribute)attrs[0]; + writer.Write(desc.Description); + } + else + { + writer.Write(SystemInfo.NotAvailableText); + } + break; + case AsmOutputType.TRADEMARK: + attrs = asm.GetCustomAttributes(typeof(AssemblyTrademarkAttribute), true); + if (attrs != null && attrs.Length == 1 && attrs[0] is AssemblyTrademarkAttribute) + { + AssemblyTrademarkAttribute tm = (AssemblyTrademarkAttribute)attrs[0]; + writer.Write(tm.Trademark); + } + else + { + writer.Write(SystemInfo.NotAvailableText); + } + break; + case AsmOutputType.TITLE: + attrs = asm.GetCustomAttributes(typeof(AssemblyTitleAttribute), true); + if (attrs != null && attrs.Length == 1 && attrs[0] is AssemblyTitleAttribute) + { + AssemblyTitleAttribute title = (AssemblyTitleAttribute)attrs[0]; + writer.Write(title.Title); + } + else + { + writer.Write(SystemInfo.NotAvailableText); + } + break; + } + } + else + { + writer.Write(SystemInfo.NotAvailableText); + } + + } + else + { + writer.Write(SystemInfo.NotAvailableText); + } + } + + #region IOptionHandler Members + + /// + /// Only want to do the option string compare the first time, after that use our + /// internal enumeration + /// + public void ActivateOptions() + { + if (string.Compare(VERSION, this.Option) == 0) + { + this.outputType = AsmOutputType.VERSION; + } + else if (string.Compare(DESCRIPTION, this.Option) == 0) + { + this.outputType = AsmOutputType.DESCRIPTION; + } + else if (string.Compare(TRADEMARK, this.Option) == 0) + { + this.outputType = AsmOutputType.TRADEMARK; + } + else if (string.Compare(TITLE, this.Option) == 0) + { + this.outputType = AsmOutputType.TITLE; + } + else + { + LogLog.Error(typeof(AsmPatternConverter), "Could not read option, must be of '" + + VERSION + "','" + + TITLE + "','" + + TRADEMARK + "', or '" + + DESCRIPTION + "', will default to Version"); + + this.outputType = AsmOutputType.VERSION; + } + } + + #endregion + } +} Index: src/Layout/PatternLayout.cs =================================================================== --- src/Layout/PatternLayout.cs (revision 675653) +++ src/Layout/PatternLayout.cs (working copy) @@ -797,7 +797,7 @@ /// static PatternLayout() { - s_globalRulesRegistry = new Hashtable(45); + s_globalRulesRegistry = new Hashtable(47); s_globalRulesRegistry.Add("literal", typeof(LiteralPatternConverter)); s_globalRulesRegistry.Add("newline", typeof(NewLinePatternConverter)); @@ -872,6 +872,8 @@ s_globalRulesRegistry.Add("w", typeof(UserNamePatternConverter)); s_globalRulesRegistry.Add("username", typeof(UserNamePatternConverter)); + + s_globalRulesRegistry.Add("asm", typeof(AsmPatternConverter)); } #endregion Static Constructor Index: src/log4net.vs2005.csproj =================================================================== --- src/log4net.vs2005.csproj (revision 675653) +++ src/log4net.vs2005.csproj (working copy) @@ -359,6 +359,7 @@ Code + Code Index: src/Repository/ILoggerRepository.cs =================================================================== --- src/Repository/ILoggerRepository.cs (revision 675653) +++ src/Repository/ILoggerRepository.cs (working copy) @@ -18,6 +18,7 @@ #endregion using System; +using System.Reflection; using System.Collections; using log4net; using log4net.ObjectRenderer; @@ -106,6 +107,15 @@ /// string Name { get; set; } + + /// + /// The assembly from which this logger repository was based on (if applicable) + /// + /// Returns null if this logger repository is based on a name instead + /// + Assembly Assembly { get; set; } + + /// /// RendererMap accesses the object renderer map for this repository. /// Index: src/Repository/LoggerRepositorySkeleton.cs =================================================================== --- src/Repository/LoggerRepositorySkeleton.cs (revision 675653) +++ src/Repository/LoggerRepositorySkeleton.cs (working copy) @@ -18,6 +18,7 @@ #endregion using System; +using System.Reflection; using System.Collections; using log4net.ObjectRenderer; using log4net.Core; @@ -55,6 +56,7 @@ private event LoggerRepositoryConfigurationResetEventHandler m_configurationResetEvent; private event LoggerRepositoryConfigurationChangedEventHandler m_configurationChangedEvent; private PropertiesDictionary m_properties; + private Assembly m_assembly; #endregion @@ -118,6 +120,15 @@ get { return m_name; } set { m_name = value; } } + + /// + /// Assembly on which this repository is based + /// + virtual public Assembly Assembly + { + get { return m_assembly; } + set { m_assembly = value; } + } /// /// The threshold for all events in this repository