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

Reply via email to