/// <summary> /// The current version of the NetStandard build of log4net does not replace environment variables. /// We will use the same functionality to replace the environment variables before we pass the xml /// into the standard XmlConfigurator /// </summary> /// <param name="xDocument"></param> private void ReplaceEnvironmentVariables(XDocument xDocument) { var environmentVariables = new Hashtable(Environment.GetEnvironmentVariables(), StringComparer.OrdinalIgnoreCase); var valueAttributes = xDocument .Descendants() .Select(x => x.Attribute("value")) .Where(x => x != null); foreach (var attribute in valueAttributes) { attribute.Value = OptionConverter.SubstituteVariables(attribute.Value, environmentVariables); } }
/// <summary> /// Sets a parameter on an object. /// </summary> /// <param name="element">The parameter element.</param> /// <param name="target">The object to set the parameter on.</param> /// <remarks> /// The parameter name must correspond to a writable property /// on the object. The value of the parameter is a string, /// therefore this function will attempt to set a string /// property first. If unable to set a string property it /// will inspect the property and its argument type. It will /// attempt to call a static method called <c>Parse</c> on the /// type of the property. This method will take a single /// string argument and return a value that can be used to /// set the property. /// </remarks> protected void SetParameter(XmlElement element, object target) { // Get the property name string name = element.GetAttribute(NAME_ATTR); // If the name attribute does not exist then use the name of the element if (element.LocalName != PARAM_TAG || name == null || name.Length == 0) { name = element.LocalName; } // Look for the property on the target object Type targetType = target.GetType(); Type propertyType = null; PropertyInfo propInfo = null; MethodInfo methInfo = null; // Try to find a writable property propInfo = targetType.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.IgnoreCase); if (propInfo != null && propInfo.CanWrite) { // found a property propertyType = propInfo.PropertyType; } else { propInfo = null; // look for a method with the signature Add<property>(type) methInfo = FindMethodInfo(targetType, name); if (methInfo != null) { propertyType = methInfo.GetParameters()[0].ParameterType; } } if (propertyType == null) { LogLog.Error(declaringType, "XmlHierarchyConfigurator: Cannot find Property [" + name + "] to set object on [" + target.ToString() + "]"); } else { string propertyValue = null; if (element.GetAttributeNode(VALUE_ATTR) != null) { propertyValue = element.GetAttribute(VALUE_ATTR); } else if (element.HasChildNodes) { // Concatenate the CDATA and Text nodes together foreach (XmlNode childNode in element.ChildNodes) { if (childNode.NodeType == XmlNodeType.CDATA || childNode.NodeType == XmlNodeType.Text) { if (propertyValue == null) { propertyValue = childNode.InnerText; } else { propertyValue += childNode.InnerText; } } } } if (propertyValue != null) { #if !NETCF try { // Expand environment variables in the string. propertyValue = OptionConverter.SubstituteVariables(propertyValue, Environment.GetEnvironmentVariables()); } catch (System.Security.SecurityException) { // This security exception will occur if the caller does not have // unrestricted environment permission. If this occurs the expansion // will be skipped with the following warning message. LogLog.Debug(declaringType, "Security exception while trying to expand environment variables. Error Ignored. No Expansion."); } #endif Type parsedObjectConversionTargetType = null; // Check if a specific subtype is specified on the element using the 'type' attribute string subTypeString = element.GetAttribute(TYPE_ATTR); if (subTypeString != null && subTypeString.Length > 0) { // Read the explicit subtype try { Type subType = SystemInfo.GetTypeFromString(subTypeString, true, true); LogLog.Debug(declaringType, "Parameter [" + name + "] specified subtype [" + subType.FullName + "]"); if (!propertyType.IsAssignableFrom(subType)) { // Check if there is an appropriate type converter if (OptionConverter.CanConvertTypeTo(subType, propertyType)) { // Must re-convert to the real property type parsedObjectConversionTargetType = propertyType; // Use sub type as intermediary type propertyType = subType; } else { LogLog.Error(declaringType, "subtype [" + subType.FullName + "] set on [" + name + "] is not a subclass of property type [" + propertyType.FullName + "] and there are no acceptable type conversions."); } } else { // The subtype specified is found and is actually a subtype of the property // type, therefore we can switch to using this type. propertyType = subType; } } catch (Exception ex) { LogLog.Error(declaringType, "Failed to find type [" + subTypeString + "] set on [" + name + "]", ex); } } // Now try to convert the string value to an acceptable type // to pass to this property. object convertedValue = ConvertStringTo(propertyType, propertyValue); // Check if we need to do an additional conversion if (convertedValue != null && parsedObjectConversionTargetType != null) { LogLog.Debug(declaringType, "Performing additional conversion of value from [" + convertedValue.GetType().Name + "] to [" + parsedObjectConversionTargetType.Name + "]"); convertedValue = OptionConverter.ConvertTypeTo(convertedValue, parsedObjectConversionTargetType); } if (convertedValue != null) { if (propInfo != null) { // Got a converted result LogLog.Debug(declaringType, "Setting Property [" + propInfo.Name + "] to " + convertedValue.GetType().Name + " value [" + convertedValue.ToString() + "]"); try { // Pass to the property propInfo.SetValue(target, convertedValue, BindingFlags.SetProperty, null, null, CultureInfo.InvariantCulture); } catch (TargetInvocationException targetInvocationEx) { LogLog.Error(declaringType, "Failed to set parameter [" + propInfo.Name + "] on object [" + target + "] using value [" + convertedValue + "]", targetInvocationEx.InnerException); } } else if (methInfo != null) { // Got a converted result LogLog.Debug(declaringType, "Setting Collection Property [" + methInfo.Name + "] to " + convertedValue.GetType().Name + " value [" + convertedValue.ToString() + "]"); try { // Pass to the property methInfo.Invoke(target, BindingFlags.InvokeMethod, null, new object[] { convertedValue }, CultureInfo.InvariantCulture); } catch (TargetInvocationException targetInvocationEx) { LogLog.Error(declaringType, "Failed to set parameter [" + name + "] on object [" + target + "] using value [" + convertedValue + "]", targetInvocationEx.InnerException); } } } else { LogLog.Warn(declaringType, "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(declaringType, "Failed to create object to set param: " + name); } else { if (propInfo != null) { // Got a converted result LogLog.Debug(declaringType, "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(declaringType, "Failed to set parameter [" + propInfo.Name + "] on object [" + target + "] using value [" + createdObject + "]", targetInvocationEx.InnerException); } } else if (methInfo != null) { // Got a converted result LogLog.Debug(declaringType, "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(declaringType, "Failed to set parameter [" + methInfo.Name + "] on object [" + target + "] using value [" + createdObject + "]", targetInvocationEx.InnerException); } } } } } }
protected void SetParameter(XmlElement element, object target) { string attribute = element.GetAttribute("name"); if ((element.LocalName != "param") || ((attribute == null) || (attribute.Length == 0))) { attribute = element.LocalName; } Type targetType = target.GetType(); Type objA = null; PropertyInfo property = null; MethodInfo info2 = null; property = targetType.GetProperty(attribute, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase); if ((property != null) && property.CanWrite) { objA = property.PropertyType; } else { property = null; info2 = this.FindMethodInfo(targetType, attribute); if (info2 != null) { objA = info2.GetParameters()[0].ParameterType; } } if (objA == null) { string[] textArray1 = new string[] { "XmlHierarchyConfigurator: Cannot find Property [", attribute, "] to set object on [", target.ToString(), "]" }; LogLog.Error(declaringType, string.Concat(textArray1)); } else { string str2 = null; if (element.GetAttributeNode("value") != null) { str2 = element.GetAttribute("value"); } else if (element.HasChildNodes) { IEnumerator enumerator = element.ChildNodes.GetEnumerator(); try { while (enumerator.MoveNext()) { XmlNode current = (XmlNode)enumerator.Current; if ((current.NodeType == XmlNodeType.CDATA) || (current.NodeType == XmlNodeType.Text)) { str2 = (str2 != null) ? (str2 + current.InnerText) : current.InnerText; } } } finally { IDisposable disposable = enumerator as IDisposable; if (disposable != null) { disposable.Dispose(); } } } if (str2 == null) { object obj3 = null; if (ReferenceEquals(objA, typeof(string)) && !this.HasAttributesOrElements(element)) { obj3 = string.Empty; } else { Type defaultTargetType = null; if (IsTypeConstructible(objA)) { defaultTargetType = objA; } obj3 = this.CreateObjectFromXml(element, defaultTargetType, objA); } if (obj3 == null) { LogLog.Error(declaringType, "Failed to create object to set param: " + attribute); } else if (property != null) { object[] objArray5 = new object[] { "Setting Property [", property.Name, "] to object [", obj3, "]" }; LogLog.Debug(declaringType, string.Concat(objArray5)); try { property.SetValue(target, obj3, BindingFlags.SetProperty, null, null, CultureInfo.InvariantCulture); } catch (TargetInvocationException exception4) { object[] objArray6 = new object[] { "Failed to set parameter [", property.Name, "] on object [", target, "] using value [", obj3, "]" }; LogLog.Error(declaringType, string.Concat(objArray6), exception4.InnerException); } } else if (info2 != null) { object[] objArray7 = new object[] { "Setting Collection Property [", info2.Name, "] to object [", obj3, "]" }; LogLog.Debug(declaringType, string.Concat(objArray7)); try { object[] parameters = new object[] { obj3 }; info2.Invoke(target, BindingFlags.InvokeMethod, null, parameters, CultureInfo.InvariantCulture); } catch (TargetInvocationException exception5) { object[] objArray9 = new object[] { "Failed to set parameter [", info2.Name, "] on object [", target, "] using value [", obj3, "]" }; LogLog.Error(declaringType, string.Concat(objArray9), exception5.InnerException); } } } else { try { IDictionary environmentVariables = Environment.GetEnvironmentVariables(); if (this.HasCaseInsensitiveEnvironment) { environmentVariables = this.CreateCaseInsensitiveWrapper(environmentVariables); } str2 = OptionConverter.SubstituteVariables(str2, environmentVariables); } catch (SecurityException) { LogLog.Debug(declaringType, "Security exception while trying to expand environment variables. Error Ignored. No Expansion."); } Type type3 = null; string typeName = element.GetAttribute("type"); if ((typeName != null) && (typeName.Length > 0)) { try { Type c = SystemInfo.GetTypeFromString(typeName, true, true); string[] textArray2 = new string[] { "Parameter [", attribute, "] specified subtype [", c.FullName, "]" }; LogLog.Debug(declaringType, string.Concat(textArray2)); if (objA.IsAssignableFrom(c)) { objA = c; } else if (OptionConverter.CanConvertTypeTo(c, objA)) { type3 = objA; objA = c; } else { string[] textArray3 = new string[] { "subtype [", c.FullName, "] set on [", attribute, "] is not a subclass of property type [", objA.FullName, "] and there are no acceptable type conversions." }; LogLog.Error(declaringType, string.Concat(textArray3)); } } catch (Exception exception) { string[] textArray4 = new string[] { "Failed to find type [", typeName, "] set on [", attribute, "]" }; LogLog.Error(declaringType, string.Concat(textArray4), exception); } } object sourceInstance = this.ConvertStringTo(objA, str2); if ((sourceInstance != null) && (type3 != null)) { string[] textArray5 = new string[] { "Performing additional conversion of value from [", sourceInstance.GetType().Name, "] to [", type3.Name, "]" }; LogLog.Debug(declaringType, string.Concat(textArray5)); sourceInstance = OptionConverter.ConvertTypeTo(sourceInstance, type3); } if (sourceInstance == null) { object[] objArray4 = new object[] { "Unable to set property [", attribute, "] on object [", target, "] using value [", str2, "] (with acceptable conversion types)" }; LogLog.Warn(declaringType, string.Concat(objArray4)); } else if (property != null) { string[] textArray6 = new string[] { "Setting Property [", property.Name, "] to ", sourceInstance.GetType().Name, " value [", sourceInstance.ToString(), "]" }; LogLog.Debug(declaringType, string.Concat(textArray6)); try { property.SetValue(target, sourceInstance, BindingFlags.SetProperty, null, null, CultureInfo.InvariantCulture); } catch (TargetInvocationException exception2) { object[] objArray1 = new object[] { "Failed to set parameter [", property.Name, "] on object [", target, "] using value [", sourceInstance, "]" }; LogLog.Error(declaringType, string.Concat(objArray1), exception2.InnerException); } } else if (info2 != null) { string[] textArray7 = new string[] { "Setting Collection Property [", info2.Name, "] to ", sourceInstance.GetType().Name, " value [", sourceInstance.ToString(), "]" }; LogLog.Debug(declaringType, string.Concat(textArray7)); try { object[] parameters = new object[] { sourceInstance }; info2.Invoke(target, BindingFlags.InvokeMethod, null, parameters, CultureInfo.InvariantCulture); } catch (TargetInvocationException exception3) { object[] objArray3 = new object[] { "Failed to set parameter [", attribute, "] on object [", target, "] using value [", sourceInstance, "]" }; LogLog.Error(declaringType, string.Concat(objArray3), exception3.InnerException); } } } } }