📄 hierarchy.cs
字号:
logger = factory.CreateLogger(name);
logger.Hierarchy = this;
m_ht[key] = logger;
UpdateChildren(nodeProvisionNode, logger);
UpdateParents(logger);
OnLoggerCreationEvent(logger);
return logger;
}
// It should be impossible to arrive here but let's keep the compiler happy.
return null;
}
}
#endregion Public Instance Methods
#region Protected Instance Methods
/// <summary>
/// Sends a logger creation event to all registered listeners
/// </summary>
/// <param name="logger">The newly created logger</param>
/// <remarks>
/// Raises the logger creation event.
/// </remarks>
protected virtual void OnLoggerCreationEvent(Logger logger)
{
LoggerCreationEventHandler handler = m_loggerCreatedEvent;
if (handler != null)
{
handler(this, new LoggerCreationEventArgs(logger));
}
}
#endregion Protected Instance Methods
#region Private Instance Methods
/// <summary>
/// Updates all the parents of the specified logger
/// </summary>
/// <param name="log">The logger to update the parents for</param>
/// <remarks>
/// <para>
/// This method loops through all the <i>potential</i> parents of
/// <paramref name="log"/>. There 3 possible cases:
/// </para>
/// <list type="number">
/// <item>
/// <term>No entry for the potential parent of <paramref name="log"/> exists</term>
/// <description>
/// We create a ProvisionNode for this potential
/// parent and insert <paramref name="log"/> in that provision node.
/// </description>
/// </item>
/// <item>
/// <term>The entry is of type Logger for the potential parent.</term>
/// <description>
/// The entry is <paramref name="log"/>'s nearest existing parent. We
/// update <paramref name="log"/>'s parent field with this entry. We also break from
/// he loop because updating our parent's parent is our parent's
/// responsibility.
/// </description>
/// </item>
/// <item>
/// <term>The entry is of type ProvisionNode for this potential parent.</term>
/// <description>
/// We add <paramref name="log"/> to the list of children for this
/// potential parent.
/// </description>
/// </item>
/// </list>
/// </remarks>
private void UpdateParents(Logger log)
{
string name = log.Name;
int length = name.Length;
bool parentFound = false;
// if name = "w.x.y.z", loop through "w.x.y", "w.x" and "w", but not "w.x.y.z"
for(int i = name.LastIndexOf('.', length-1); i >= 0; i = name.LastIndexOf('.', i-1))
{
string substr = name.Substring(0, i);
LoggerKey key = new LoggerKey(substr); // simple constructor
Object node = m_ht[key];
// Create a provision node for a future parent.
if (node == null)
{
ProvisionNode pn = new ProvisionNode(log);
m_ht[key] = pn;
}
else
{
Logger nodeLogger = node as Logger;
if (nodeLogger != null)
{
parentFound = true;
log.Parent = nodeLogger;
break; // no need to update the ancestors of the closest ancestor
}
else
{
ProvisionNode nodeProvisionNode = node as ProvisionNode;
if (nodeProvisionNode != null)
{
nodeProvisionNode.Add(log);
}
else
{
LogLog.Error("Hierarchy: Unexpected object type ["+node.GetType()+"] in ht.", new LogException());
}
}
}
}
// If we could not find any existing parents, then link with root.
if (!parentFound)
{
log.Parent = this.Root;
}
}
/// <summary>
/// Replace a <see cref="ProvisionNode"/> with a <see cref="Logger"/> in the hierarchy.
/// </summary>
/// <param name="pn"></param>
/// <param name="log"></param>
/// <remarks>
/// <para>
/// We update the links for all the children that placed themselves
/// in the provision node 'pn'. The second argument 'log' is a
/// reference for the newly created Logger, parent of all the
/// children in 'pn'.
/// </para>
/// <para>
/// We loop on all the children 'c' in 'pn'.
/// </para>
/// <para>
/// If the child 'c' has been already linked to a child of
/// 'log' then there is no need to update 'c'.
/// </para>
/// <para>
/// Otherwise, we set log's parent field to c's parent and set
/// c's parent field to log.
/// </para>
/// </remarks>
private void UpdateChildren(ProvisionNode pn, Logger log)
{
for(int i = 0; i < pn.Count; i++)
{
Logger childLogger = (Logger)pn[i];
// Unless this child already points to a correct (lower) parent,
// make log.Parent point to childLogger.Parent and childLogger.Parent to log.
if (!childLogger.Parent.Name.StartsWith(log.Name))
{
log.Parent = childLogger.Parent;
childLogger.Parent = log;
}
}
}
/// <summary>
/// Define or redefine a Level using the values in the <see cref="LevelEntry"/> argument
/// </summary>
/// <param name="levelEntry">the level values</param>
/// <remarks>
/// <para>
/// Define or redefine a Level using the values in the <see cref="LevelEntry"/> argument
/// </para>
/// <para>
/// Supports setting levels via the configuration file.
/// </para>
/// </remarks>
internal void AddLevel(LevelEntry levelEntry)
{
if (levelEntry == null) throw new ArgumentNullException("levelEntry");
if (levelEntry.Name == null) throw new ArgumentNullException("levelEntry.Name");
// Lookup replacement value
if (levelEntry.Value == -1)
{
Level previousLevel = LevelMap[levelEntry.Name];
if (previousLevel == null)
{
throw new InvalidOperationException("Cannot redefine level ["+levelEntry.Name+"] because it is not defined in the LevelMap. To define the level supply the level value.");
}
levelEntry.Value = previousLevel.Value;
}
LevelMap.Add(levelEntry.Name, levelEntry.Value, levelEntry.DisplayName);
}
/// <summary>
/// A class to hold the value, name and display name for a level
/// </summary>
/// <remarks>
/// <para>
/// A class to hold the value, name and display name for a level
/// </para>
/// </remarks>
internal class LevelEntry
{
private int m_levelValue = -1;
private string m_levelName = null;
private string m_levelDisplayName = null;
/// <summary>
/// Value of the level
/// </summary>
/// <remarks>
/// <para>
/// If the value is not set (defaults to -1) the value will be looked
/// up for the current level with the same name.
/// </para>
/// </remarks>
public int Value
{
get { return m_levelValue; }
set { m_levelValue = value; }
}
/// <summary>
/// Name of the level
/// </summary>
/// <value>
/// The name of the level
/// </value>
/// <remarks>
/// <para>
/// The name of the level.
/// </para>
/// </remarks>
public string Name
{
get { return m_levelName; }
set { m_levelName = value; }
}
/// <summary>
/// Display name for the level
/// </summary>
/// <value>
/// The display name of the level
/// </value>
/// <remarks>
/// <para>
/// The display name of the level.
/// </para>
/// </remarks>
public string DisplayName
{
get { return m_levelDisplayName; }
set { m_levelDisplayName = value; }
}
/// <summary>
/// Override <c>Object.ToString</c> to return sensible debug info
/// </summary>
/// <returns>string info about this object</returns>
public override string ToString()
{
return "LevelEntry(Value="+m_levelValue+", Name="+m_levelName+", DisplayName="+m_levelDisplayName+")";
}
}
/// <summary>
/// Set a Property using the values in the <see cref="LevelEntry"/> argument
/// </summary>
/// <param name="propertyEntry">the property value</param>
/// <remarks>
/// <para>
/// Set a Property using the values in the <see cref="LevelEntry"/> argument.
/// </para>
/// <para>
/// Supports setting property values via the configuration file.
/// </para>
/// </remarks>
internal void AddProperty(PropertyEntry propertyEntry)
{
if (propertyEntry == null) throw new ArgumentNullException("propertyEntry");
if (propertyEntry.Key == null) throw new ArgumentNullException("propertyEntry.Key");
Properties[propertyEntry.Key] = propertyEntry.Value;
}
/// <summary>
/// A class to hold the key and data for a property set in the config file
/// </summary>
/// <remarks>
/// <para>
/// A class to hold the key and data for a property set in the config file
/// </para>
/// </remarks>
internal class PropertyEntry
{
private string m_key = null;
private object m_value = null;
/// <summary>
/// Property Key
/// </summary>
/// <value>
/// Property Key
/// </value>
/// <remarks>
/// <para>
/// Property Key.
/// </para>
/// </remarks>
public string Key
{
get { return m_key; }
set { m_key = value; }
}
/// <summary>
/// Property Value
/// </summary>
/// <value>
/// Property Value
/// </value>
/// <remarks>
/// <para>
/// Property Value.
/// </para>
/// </remarks>
public object Value
{
get { return m_value; }
set { m_value = value; }
}
/// <summary>
/// Override <c>Object.ToString</c> to return sensible debug info
/// </summary>
/// <returns>string info about this object</returns>
public override string ToString()
{
return "PropertyEntry(Key="+m_key+", Value="+m_value+")";
}
}
#endregion Private Instance Methods
#region Private Instance Fields
private ILoggerFactory m_defaultFactory;
private System.Collections.Hashtable m_ht;
private Logger m_root;
private bool m_emittedNoAppenderWarning = false;
private event LoggerCreationEventHandler m_loggerCreatedEvent;
#endregion Private Instance Fields
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -