Support for types of non-parameterless constructors in XmlConfigurator. The constructor parameters are taken from the corresponding values of the child nodes.
You can add for instance <standardunit type="Amazon.CloudWatch.StandardUnit"> <value value="Kilobytes"/> </standardunit> where StandardUnit has only one constructor that has a string parameter named "value". Project: http://git-wip-us.apache.org/repos/asf/logging-log4net/repo Commit: http://git-wip-us.apache.org/repos/asf/logging-log4net/commit/b4bc43ee Tree: http://git-wip-us.apache.org/repos/asf/logging-log4net/tree/b4bc43ee Diff: http://git-wip-us.apache.org/repos/asf/logging-log4net/diff/b4bc43ee Branch: refs/heads/pr/old/10 Commit: b4bc43eed24d1152772141652d68002f396c615d Parents: 610157a Author: Martin Camitz <[email protected]> Authored: Tue Apr 22 15:36:29 2014 +0200 Committer: Dominik Psenner <[email protected]> Committed: Thu May 25 00:06:48 2017 +0200 ---------------------------------------------------------------------- .../Hierarchy/XmlHierarchyConfigurator.cs | 54 ++++++++++++++++++-- 1 file changed, 50 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4net/blob/b4bc43ee/src/log4net/Repository/Hierarchy/XmlHierarchyConfigurator.cs ---------------------------------------------------------------------- diff --git a/src/log4net/Repository/Hierarchy/XmlHierarchyConfigurator.cs b/src/log4net/Repository/Hierarchy/XmlHierarchyConfigurator.cs index ae415d7..a251b47 100644 --- a/src/log4net/Repository/Hierarchy/XmlHierarchyConfigurator.cs +++ b/src/log4net/Repository/Hierarchy/XmlHierarchyConfigurator.cs @@ -19,7 +19,9 @@ using System; using System.Collections; +using System.Collections.Generic; using System.Globalization; +using System.Linq; using System.Reflection; using System.Xml; @@ -986,13 +988,57 @@ namespace log4net.Repository.Hierarchy // Create using the default constructor object createdObject = null; - try + + //Try parameterless constructor + if (objectType.GetConstructor(Type.EmptyTypes) != null) { - createdObject = Activator.CreateInstance(objectType); + try + { + createdObject = Activator.CreateInstance(objectType); + } + catch (Exception createInstanceEx) + { + LogLog.Error(declaringType, + "XmlHierarchyConfigurator: Failed to construct object of type [" + objectType.FullName + + "] Exception: " + createInstanceEx.ToString()); + } + } - catch(Exception createInstanceEx) + else { - LogLog.Error(declaringType, "XmlHierarchyConfigurator: Failed to construct object of type [" + objectType.FullName + "] Exception: "+createInstanceEx.ToString()); + //See if there is a constructor matching supplied values, most specific first. + Exception lastException = null; + foreach (var constructorInfo in objectType.GetConstructors().OrderByDescending(x => x.GetParameters().Count())) + { + + try + { + var nodes = new List<XmlNode>(element.ChildNodes.Cast<XmlNode>()); + var parameterInfos = constructorInfo.GetParameters(); + LogLog.Debug(declaringType, "Trying constructor with parameters: " + string.Join(",", parameterInfos.Select(p => p.Name))); + + var args = parameterInfos.Select(p => nodes.SingleOrDefault(n => n.Name == p.Name)); + LogLog.Debug(declaringType, "Matching args from config: " + string.Join(",", args.Select(n => n.Name))); + LogLog.Debug(declaringType, "Matching arg values from config: " + string.Join(",", args.Select(a => a.Attributes["value"].Value))); + if (args.All(a => a != null)) + { + createdObject = constructorInfo.Invoke(args.Select(a => a.Attributes["value"].Value).ToArray()); + break; + } + } + catch (Exception e) + { + lastException = e; + } + } + + if (createdObject == null) + { + LogLog.Error(declaringType, + "XmlHierarchyConfigurator: Failed to construct object of type [" + objectType.FullName + + "] No matching constructor found. LastException: " + + (lastException != null ? lastException.ToString() : "None caught.")); + } } // Set any params on object
