Uploaded image for project: 'Spring.NET'
  1. Spring.NET
  2. SPRNET-1512

Spring.Context.Support.AbstractApplicationContext.GetObjectNamesForType(..) fails to account for parent ApplicationContext/ObjectFactory object definitions



    • Type: Task
    • Status: Resolved
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 2.0 M1
    • Fix Version/s: 2.0 M2
    • Component/s: Spring-NET-CORE
    • Labels:


      The following test illustrates the problem...

      public class TheTest
      public void Test()

      { var parentObjectDefinition = new RootObjectDefinition(typeof (ObjectInParent)); var childObjectDefinition = new RootObjectDefinition(typeof (ObjectInChild)); var parent = new GenericApplicationContext(); parent.RegisterObjectDefinition("objectInParent", parentObjectDefinition); var child = new GenericApplicationContext(parent); child.RegisterObjectDefinition("objectInChild", childObjectDefinition); parent.Refresh(); child.Refresh(); //parent ctx can resolve just its own registered object Assert.That(parent.GetObject<ObjectInParent>(), Is.Not.Null); Assert.That(parent.GetObject("objectInParent"), Is.Not.Null); //child can resolve its own registered object... Assert.That(child.GetObject<ObjectInChild>(), Is.Not.Null); Assert.That(child.GetObject("objectInChild"), Is.Not.Null); //child can delegate to parent to resolve the parent's object Assert.That(child.GetObject<ObjectInParent>(), Is.Not.Null); // <-- this FAILs Assert.That(child.GetObject("objectInParent"), Is.Not.Null); // <-- this PASSes }


      public class ObjectInParent


      public class ObjectInChild


      The problem with this test is that .GetObject(string name) properly respects parent/child hierarchies of ApplicationContexts/ObjectFactories but the new .GetObject<T>() does not.

      I have tracked this down to the fact that .GetObject<T>() relies upon Spring.Context.Support.AbstractApplicationContext.GetObjectNamesForType(...) which in turn eventually calls Spring.Objects.Factory.Support.DefaultListableObjectFactory.DoGetNamesForType(...) .

      Unfortunately, DefaultListableObjectFactory.DoGetNamesForType(...) only inspects the current ObjectFactory's object definition names and then any manually-registered singletons before it returns all matches. This code-path NEVER bothers to inspect object definitions for any PARENT object factories, which is why our code-path from GetObject<T>() fails to respect the context/factory parent-child hierarchy.

      To fix this will require changing the definition of DefaultListableObjectFactory.GetObjectDefinitionNames() and DefaultListableObjectFactory.GetSingletonNames() to check for a non-null ParentObjectFactory and then 'merge' the names from the non-null Parent with its own. Then in the body of DefaultListableObjectFactory.DoGetNamesForType(...) we will need to change the call to GetMergedObjectDefinitions(...) to pass a true for the second arg instead of false. This would permit GetMergedObjectDefinitions(...) to traverse to parent factory/contexts when it searches for the ROD to return and should solve the problem.




            sbohlen Steve Bohlen
            sbohlen Steve Bohlen
            0 Vote for this issue
            1 Start watching this issue