📄 xmlhierarchyconfigurator.cs
字号:
try
{
// Pass to the property
methInfo.Invoke(target, BindingFlags.InvokeMethod, null, new object[] {convertedValue}, CultureInfo.InvariantCulture);
}
catch(TargetInvocationException targetInvocationEx)
{
LogLog.Error("XmlHierarchyConfigurator: Failed to set parameter [" + name + "] on object [" + target + "] using value [" + convertedValue + "]", targetInvocationEx.InnerException);
}
}
}
else
{
LogLog.Warn("XmlHierarchyConfigurator: Unable to set property [" + name + "] on object [" + target + "] using value [" + propertyValue + "] (with acceptable conversion types)");
}
}
else
{
object createdObject = null;
if (propertyType == typeof(string) && !HasAttributesOrElements(element))
{
// If the property is a string and the element is empty (no attributes
// or child elements) then we special case the object value to an empty string.
// This is necessary because while the String is a class it does not have
// a default constructor that creates an empty string, which is the behavior
// we are trying to simulate and would be expected from CreateObjectFromXml
createdObject = "";
}
else
{
// No value specified
Type defaultObjectType = null;
if (IsTypeConstructible(propertyType))
{
defaultObjectType = propertyType;
}
createdObject = CreateObjectFromXml(element, defaultObjectType, propertyType);
}
if (createdObject == null)
{
LogLog.Error("XmlHierarchyConfigurator: Failed to create object to set param: "+name);
}
else
{
if (propInfo != null)
{
// Got a converted result
LogLog.Debug("XmlHierarchyConfigurator: Setting Property ["+ propInfo.Name +"] to object ["+ createdObject +"]");
try
{
// Pass to the property
propInfo.SetValue(target, createdObject, BindingFlags.SetProperty, null, null, CultureInfo.InvariantCulture);
}
catch(TargetInvocationException targetInvocationEx)
{
LogLog.Error("XmlHierarchyConfigurator: Failed to set parameter [" + propInfo.Name + "] on object [" + target + "] using value [" + createdObject + "]", targetInvocationEx.InnerException);
}
}
else if (methInfo != null)
{
// Got a converted result
LogLog.Debug("XmlHierarchyConfigurator: Setting Collection Property ["+ methInfo.Name +"] to object ["+ createdObject +"]");
try
{
// Pass to the property
methInfo.Invoke(target, BindingFlags.InvokeMethod, null, new object[] {createdObject}, CultureInfo.InvariantCulture);
}
catch(TargetInvocationException targetInvocationEx)
{
LogLog.Error("XmlHierarchyConfigurator: Failed to set parameter [" + methInfo.Name + "] on object [" + target + "] using value [" + createdObject + "]", targetInvocationEx.InnerException);
}
}
}
}
}
}
/// <summary>
/// Test if an element has no attributes or child elements
/// </summary>
/// <param name="element">the element to inspect</param>
/// <returns><c>true</c> if the element has any attributes or child elements, <c>false</c> otherwise</returns>
private bool HasAttributesOrElements(XmlElement element)
{
foreach(XmlNode node in element.ChildNodes)
{
if (node.NodeType == XmlNodeType.Attribute || node.NodeType == XmlNodeType.Element)
{
return true;
}
}
return false;
}
/// <summary>
/// Test if a <see cref="Type"/> is constructible with <c>Activator.CreateInstance</c>.
/// </summary>
/// <param name="type">the type to inspect</param>
/// <returns><c>true</c> if the type is creatable using a default constructor, <c>false</c> otherwise</returns>
private static bool IsTypeConstructible(Type type)
{
if (type.IsClass && !type.IsAbstract)
{
ConstructorInfo defaultConstructor = type.GetConstructor(new Type[0]);
if (defaultConstructor != null && !defaultConstructor.IsAbstract && !defaultConstructor.IsPrivate)
{
return true;
}
}
return false;
}
/// <summary>
/// Look for a method on the <paramref name="targetType"/> that matches the <paramref name="name"/> supplied
/// </summary>
/// <param name="targetType">the type that has the method</param>
/// <param name="name">the name of the method</param>
/// <returns>the method info found</returns>
/// <remarks>
/// <para>
/// The method must be a public instance method on the <paramref name="targetType"/>.
/// The method must be named <paramref name="name"/> or "Add" followed by <paramref name="name"/>.
/// The method must take a single parameter.
/// </para>
/// </remarks>
private MethodInfo FindMethodInfo(Type targetType, string name)
{
string requiredMethodNameA = name;
string requiredMethodNameB = "Add" + name;
MethodInfo[] methods = targetType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach(MethodInfo methInfo in methods)
{
if (!methInfo.IsStatic)
{
if (string.Compare(methInfo.Name, requiredMethodNameA, true, System.Globalization.CultureInfo.InvariantCulture) == 0 ||
string.Compare(methInfo.Name, requiredMethodNameB, true, System.Globalization.CultureInfo.InvariantCulture) == 0)
{
// Found matching method name
// Look for version with one arg only
System.Reflection.ParameterInfo[] methParams = methInfo.GetParameters();
if (methParams.Length == 1)
{
return methInfo;
}
}
}
}
return null;
}
/// <summary>
/// Converts a string value to a target type.
/// </summary>
/// <param name="type">The type of object to convert the string to.</param>
/// <param name="value">The string value to use as the value of the object.</param>
/// <returns>
/// <para>
/// An object of type <paramref name="type"/> with value <paramref name="value"/> or
/// <c>null</c> when the conversion could not be performed.
/// </para>
/// </returns>
protected object ConvertStringTo(Type type, string value)
{
// Hack to allow use of Level in property
if (typeof(Level) == type)
{
// Property wants a level
Level levelValue = m_hierarchy.LevelMap[value];
if (levelValue == null)
{
LogLog.Error("XmlHierarchyConfigurator: Unknown Level Specified ["+ value +"]");
}
return levelValue;
}
return OptionConverter.ConvertStringTo(type, value);
}
/// <summary>
/// Creates an object as specified in XML.
/// </summary>
/// <param name="element">The XML element that contains the definition of the object.</param>
/// <param name="defaultTargetType">The object type to use if not explicitly specified.</param>
/// <param name="typeConstraint">The type that the returned object must be or must inherit from.</param>
/// <returns>The object or <c>null</c></returns>
/// <remarks>
/// <para>
/// Parse an XML element and create an object instance based on the configuration
/// data.
/// </para>
/// <para>
/// The type of the instance may be specified in the XML. If not
/// specified then the <paramref name="defaultTargetType"/> is used
/// as the type. However the type is specified it must support the
/// <paramref name="typeConstraint"/> type.
/// </para>
/// </remarks>
protected object CreateObjectFromXml(XmlElement element, Type defaultTargetType, Type typeConstraint)
{
Type objectType = null;
// Get the object type
string objectTypeString = element.GetAttribute(TYPE_ATTR);
if (objectTypeString == null || objectTypeString.Length == 0)
{
if (defaultTargetType == null)
{
LogLog.Error("XmlHierarchyConfigurator: Object type not specified. Cannot create object of type ["+typeConstraint.FullName+"]. Missing Value or Type.");
return null;
}
else
{
// Use the default object type
objectType = defaultTargetType;
}
}
else
{
// Read the explicit object type
try
{
objectType = SystemInfo.GetTypeFromString(objectTypeString, true, true);
}
catch(Exception ex)
{
LogLog.Error("XmlHierarchyConfigurator: Failed to find type ["+objectTypeString+"]", ex);
return null;
}
}
bool requiresConversion = false;
// Got the object type. Check that it meets the typeConstraint
if (typeConstraint != null)
{
if (!typeConstraint.IsAssignableFrom(objectType))
{
// Check if there is an appropriate type converter
if (OptionConverter.CanConvertTypeTo(objectType, typeConstraint))
{
requiresConversion = true;
}
else
{
LogLog.Error("XmlHierarchyConfigurator: Object type ["+objectType.FullName+"] is not assignable to type ["+typeConstraint.FullName+"]. There are no acceptable type conversions.");
return null;
}
}
}
// Create using the default constructor
object createdObject = null;
try
{
createdObject = Activator.CreateInstance(objectType);
}
catch(Exception createInstanceEx)
{
LogLog.Error("XmlHierarchyConfigurator: Failed to construct object of type [" + objectType.FullName + "] Exception: "+createInstanceEx.ToString());
}
// Set any params on object
foreach (XmlNode currentNode in element.ChildNodes)
{
if (currentNode.NodeType == XmlNodeType.Element)
{
SetParameter((XmlElement)currentNode, createdObject);
}
}
// Check if we need to call ActivateOptions
IOptionHandler optionHandler = createdObject as IOptionHandler;
if (optionHandler != null)
{
optionHandler.ActivateOptions();
}
// Ok object should be initialized
if (requiresConversion)
{
// Convert the object type
return OptionConverter.ConvertTypeTo(createdObject, typeConstraint);
}
else
{
// The object is of the correct type
return createdObject;
}
}
#endregion Protected Instance Methods
#region Private Constants
// String constants used while parsing the XML data
private const string CONFIGURATION_TAG = "log4net";
private const string RENDERER_TAG = "renderer";
private const string APPENDER_TAG = "appender";
private const string APPENDER_REF_TAG = "appender-ref";
private const string PARAM_TAG = "param";
// TODO: Deprecate use of category tags
private const string CATEGORY_TAG = "category";
// TODO: Deprecate use of priority tag
private const string PRIORITY_TAG = "priority";
private const string LOGGER_TAG = "logger";
private const string NAME_ATTR = "name";
private const string TYPE_ATTR = "type";
private const string VALUE_ATTR = "value";
private const string ROOT_TAG = "root";
private const string LEVEL_TAG = "level";
private const string REF_ATTR = "ref";
private const string ADDITIVITY_ATTR = "additivity";
private const string THRESHOLD_ATTR = "threshold";
private const string CONFIG_DEBUG_ATTR = "configDebug";
private const string INTERNAL_DEBUG_ATTR = "debug";
private const string CONFIG_UPDATE_MODE_ATTR = "update";
private const string RENDERING_TYPE_ATTR = "renderingClass";
private const string RENDERED_TYPE_ATTR = "renderedClass";
// flag used on the level element
private const string INHERITED = "inherited";
#endregion Private Constants
#region Private Instance Fields
/// <summary>
/// key: appenderName, value: appender.
/// </summary>
private Hashtable m_appenderBag;
/// <summary>
/// The Hierarchy being configured.
/// </summary>
private readonly Hierarchy m_hierarchy;
#endregion Private Instance Fields
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -