⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xmlhierarchyconfigurator.cs

📁 网上书店系统
💻 CS
📖 第 1 页 / 共 3 页
字号:
							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 + -