How to delegate Container1.Resolve to Container2.Resolve, if Container1 cannot resolve T?










1















Using Spring4D, I would like to build a container that delegates service resolution to another container, if it cannot resolve a service -- something along these lines:



function TContainer.Resolve<T>: T;
begin
if not TryResolve<T>(Result) then
Result := OtherContainer.Resolve<T>;
end;


Is this possible?










share|improve this question




























    1















    Using Spring4D, I would like to build a container that delegates service resolution to another container, if it cannot resolve a service -- something along these lines:



    function TContainer.Resolve<T>: T;
    begin
    if not TryResolve<T>(Result) then
    Result := OtherContainer.Resolve<T>;
    end;


    Is this possible?










    share|improve this question


























      1












      1








      1








      Using Spring4D, I would like to build a container that delegates service resolution to another container, if it cannot resolve a service -- something along these lines:



      function TContainer.Resolve<T>: T;
      begin
      if not TryResolve<T>(Result) then
      Result := OtherContainer.Resolve<T>;
      end;


      Is this possible?










      share|improve this question
















      Using Spring4D, I would like to build a container that delegates service resolution to another container, if it cannot resolve a service -- something along these lines:



      function TContainer.Resolve<T>: T;
      begin
      if not TryResolve<T>(Result) then
      Result := OtherContainer.Resolve<T>;
      end;


      Is this possible?







      dependency-injection spring4d






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 12 '18 at 16:05









      Cœur

      17.6k9105145




      17.6k9105145










      asked Sep 23 '17 at 22:51









      MaxMax

      304112




      304112






















          1 Answer
          1






          active

          oldest

          votes


















          1














          There are so called subdependency resolvers (future versions will just call them type resolver) inside a container that handle specific types or type patterns (like being able to resolve TArray<T> or IList<T> where T is something being registered).



          You can implement your own that checks if a type is not inside of the container you attached this resolver to and then delegate the resolve chain for this type to another container.



          Here is some example code how to achieve that (without freeing objects)



          uses
          Spring,
          Spring.Container,
          Spring.Container.Core,
          System.SysUtils;

          type
          TFoo = class

          end;

          TBar = class
          private
          fFoo: TFoo;
          public
          constructor Create(const foo: TFoo);
          property Foo: TFoo read fFoo;
          end;

          TSubContainerResolver = class(TInterfacedObject, ISubDependencyResolver)
          private
          fContainer: TContainer;
          fSubContainer: TContainer;
          public
          constructor Create(const container, subContainer: TContainer);

          function CanResolve(const context: ICreationContext;
          const dependency: TDependencyModel; const argument: TValue): Boolean;
          function Resolve(const context: ICreationContext;
          const dependency: TDependencyModel; const argument: TValue): TValue;
          end;

          TBar

          constructor TBar.Create(const foo: TFoo);
          begin
          fFoo := foo;
          end;

          TSubContainerResolver

          constructor TSubContainerResolver.Create(const container, subContainer: TContainer);
          begin
          fContainer := container;
          fSubContainer := subContainer;
          end;

          function TSubContainerResolver.CanResolve(const context: ICreationContext;
          const dependency: TDependencyModel; const argument: TValue): Boolean;
          begin
          Result := not fContainer.Kernel.Registry.HasService(dependency.TypeInfo)
          and fSubContainer.Kernel.Resolver.CanResolve(context, dependency, argument);
          end;

          function TSubContainerResolver.Resolve(const context: ICreationContext;
          const dependency: TDependencyModel; const argument: TValue): TValue;
          begin
          Result := fSubContainer.Kernel.Resolver.Resolve(context, dependency, argument);
          end;

          procedure ScenarioOne;
          var
          c1, c2: TContainer;
          b: TBar;
          begin
          c1 := TContainer.Create;
          c2 := TContainer.Create;
          c1.Kernel.Resolver.AddSubResolver(TSubContainerResolver.Create(c1, c2));

          // dependency in subcontainer
          c1.RegisterType<TBar>;
          c1.Build;
          c2.RegisterType<TFoo>;
          c2.Build;

          b := c1.Resolve<TBar>;
          Assert(Assigned(b.fFoo));
          end;

          procedure ScenarioTwo;
          var
          c1, c2: TContainer;
          b: TBar;
          begin
          c1 := TContainer.Create;
          c2 := TContainer.Create;

          c1.Kernel.Resolver.AddSubResolver(TSubContainerResolver.Create(c1, c2));
          c2.Kernel.Resolver.AddSubResolver(TSubContainerResolver.Create(c2, c1));

          // type in subcontainer but dependency in parent container
          c1.RegisterType<TFoo>;
          c1.Build;
          c2.RegisterType<TBar>;
          c2.Build;

          b := c1.Resolve<TBar>;
          Assert(Assigned(b.fFoo));
          end;

          begin
          ScenarioOne;
          ScenarioTwo;
          end.





          share|improve this answer
























            Your Answer






            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "1"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader:
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            ,
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













            draft saved

            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f46384964%2fhow-to-delegate-container1-resolvet-to-container2-resolvet-if-container1-ca%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            1














            There are so called subdependency resolvers (future versions will just call them type resolver) inside a container that handle specific types or type patterns (like being able to resolve TArray<T> or IList<T> where T is something being registered).



            You can implement your own that checks if a type is not inside of the container you attached this resolver to and then delegate the resolve chain for this type to another container.



            Here is some example code how to achieve that (without freeing objects)



            uses
            Spring,
            Spring.Container,
            Spring.Container.Core,
            System.SysUtils;

            type
            TFoo = class

            end;

            TBar = class
            private
            fFoo: TFoo;
            public
            constructor Create(const foo: TFoo);
            property Foo: TFoo read fFoo;
            end;

            TSubContainerResolver = class(TInterfacedObject, ISubDependencyResolver)
            private
            fContainer: TContainer;
            fSubContainer: TContainer;
            public
            constructor Create(const container, subContainer: TContainer);

            function CanResolve(const context: ICreationContext;
            const dependency: TDependencyModel; const argument: TValue): Boolean;
            function Resolve(const context: ICreationContext;
            const dependency: TDependencyModel; const argument: TValue): TValue;
            end;

            TBar

            constructor TBar.Create(const foo: TFoo);
            begin
            fFoo := foo;
            end;

            TSubContainerResolver

            constructor TSubContainerResolver.Create(const container, subContainer: TContainer);
            begin
            fContainer := container;
            fSubContainer := subContainer;
            end;

            function TSubContainerResolver.CanResolve(const context: ICreationContext;
            const dependency: TDependencyModel; const argument: TValue): Boolean;
            begin
            Result := not fContainer.Kernel.Registry.HasService(dependency.TypeInfo)
            and fSubContainer.Kernel.Resolver.CanResolve(context, dependency, argument);
            end;

            function TSubContainerResolver.Resolve(const context: ICreationContext;
            const dependency: TDependencyModel; const argument: TValue): TValue;
            begin
            Result := fSubContainer.Kernel.Resolver.Resolve(context, dependency, argument);
            end;

            procedure ScenarioOne;
            var
            c1, c2: TContainer;
            b: TBar;
            begin
            c1 := TContainer.Create;
            c2 := TContainer.Create;
            c1.Kernel.Resolver.AddSubResolver(TSubContainerResolver.Create(c1, c2));

            // dependency in subcontainer
            c1.RegisterType<TBar>;
            c1.Build;
            c2.RegisterType<TFoo>;
            c2.Build;

            b := c1.Resolve<TBar>;
            Assert(Assigned(b.fFoo));
            end;

            procedure ScenarioTwo;
            var
            c1, c2: TContainer;
            b: TBar;
            begin
            c1 := TContainer.Create;
            c2 := TContainer.Create;

            c1.Kernel.Resolver.AddSubResolver(TSubContainerResolver.Create(c1, c2));
            c2.Kernel.Resolver.AddSubResolver(TSubContainerResolver.Create(c2, c1));

            // type in subcontainer but dependency in parent container
            c1.RegisterType<TFoo>;
            c1.Build;
            c2.RegisterType<TBar>;
            c2.Build;

            b := c1.Resolve<TBar>;
            Assert(Assigned(b.fFoo));
            end;

            begin
            ScenarioOne;
            ScenarioTwo;
            end.





            share|improve this answer





























              1














              There are so called subdependency resolvers (future versions will just call them type resolver) inside a container that handle specific types or type patterns (like being able to resolve TArray<T> or IList<T> where T is something being registered).



              You can implement your own that checks if a type is not inside of the container you attached this resolver to and then delegate the resolve chain for this type to another container.



              Here is some example code how to achieve that (without freeing objects)



              uses
              Spring,
              Spring.Container,
              Spring.Container.Core,
              System.SysUtils;

              type
              TFoo = class

              end;

              TBar = class
              private
              fFoo: TFoo;
              public
              constructor Create(const foo: TFoo);
              property Foo: TFoo read fFoo;
              end;

              TSubContainerResolver = class(TInterfacedObject, ISubDependencyResolver)
              private
              fContainer: TContainer;
              fSubContainer: TContainer;
              public
              constructor Create(const container, subContainer: TContainer);

              function CanResolve(const context: ICreationContext;
              const dependency: TDependencyModel; const argument: TValue): Boolean;
              function Resolve(const context: ICreationContext;
              const dependency: TDependencyModel; const argument: TValue): TValue;
              end;

              TBar

              constructor TBar.Create(const foo: TFoo);
              begin
              fFoo := foo;
              end;

              TSubContainerResolver

              constructor TSubContainerResolver.Create(const container, subContainer: TContainer);
              begin
              fContainer := container;
              fSubContainer := subContainer;
              end;

              function TSubContainerResolver.CanResolve(const context: ICreationContext;
              const dependency: TDependencyModel; const argument: TValue): Boolean;
              begin
              Result := not fContainer.Kernel.Registry.HasService(dependency.TypeInfo)
              and fSubContainer.Kernel.Resolver.CanResolve(context, dependency, argument);
              end;

              function TSubContainerResolver.Resolve(const context: ICreationContext;
              const dependency: TDependencyModel; const argument: TValue): TValue;
              begin
              Result := fSubContainer.Kernel.Resolver.Resolve(context, dependency, argument);
              end;

              procedure ScenarioOne;
              var
              c1, c2: TContainer;
              b: TBar;
              begin
              c1 := TContainer.Create;
              c2 := TContainer.Create;
              c1.Kernel.Resolver.AddSubResolver(TSubContainerResolver.Create(c1, c2));

              // dependency in subcontainer
              c1.RegisterType<TBar>;
              c1.Build;
              c2.RegisterType<TFoo>;
              c2.Build;

              b := c1.Resolve<TBar>;
              Assert(Assigned(b.fFoo));
              end;

              procedure ScenarioTwo;
              var
              c1, c2: TContainer;
              b: TBar;
              begin
              c1 := TContainer.Create;
              c2 := TContainer.Create;

              c1.Kernel.Resolver.AddSubResolver(TSubContainerResolver.Create(c1, c2));
              c2.Kernel.Resolver.AddSubResolver(TSubContainerResolver.Create(c2, c1));

              // type in subcontainer but dependency in parent container
              c1.RegisterType<TFoo>;
              c1.Build;
              c2.RegisterType<TBar>;
              c2.Build;

              b := c1.Resolve<TBar>;
              Assert(Assigned(b.fFoo));
              end;

              begin
              ScenarioOne;
              ScenarioTwo;
              end.





              share|improve this answer



























                1












                1








                1







                There are so called subdependency resolvers (future versions will just call them type resolver) inside a container that handle specific types or type patterns (like being able to resolve TArray<T> or IList<T> where T is something being registered).



                You can implement your own that checks if a type is not inside of the container you attached this resolver to and then delegate the resolve chain for this type to another container.



                Here is some example code how to achieve that (without freeing objects)



                uses
                Spring,
                Spring.Container,
                Spring.Container.Core,
                System.SysUtils;

                type
                TFoo = class

                end;

                TBar = class
                private
                fFoo: TFoo;
                public
                constructor Create(const foo: TFoo);
                property Foo: TFoo read fFoo;
                end;

                TSubContainerResolver = class(TInterfacedObject, ISubDependencyResolver)
                private
                fContainer: TContainer;
                fSubContainer: TContainer;
                public
                constructor Create(const container, subContainer: TContainer);

                function CanResolve(const context: ICreationContext;
                const dependency: TDependencyModel; const argument: TValue): Boolean;
                function Resolve(const context: ICreationContext;
                const dependency: TDependencyModel; const argument: TValue): TValue;
                end;

                TBar

                constructor TBar.Create(const foo: TFoo);
                begin
                fFoo := foo;
                end;

                TSubContainerResolver

                constructor TSubContainerResolver.Create(const container, subContainer: TContainer);
                begin
                fContainer := container;
                fSubContainer := subContainer;
                end;

                function TSubContainerResolver.CanResolve(const context: ICreationContext;
                const dependency: TDependencyModel; const argument: TValue): Boolean;
                begin
                Result := not fContainer.Kernel.Registry.HasService(dependency.TypeInfo)
                and fSubContainer.Kernel.Resolver.CanResolve(context, dependency, argument);
                end;

                function TSubContainerResolver.Resolve(const context: ICreationContext;
                const dependency: TDependencyModel; const argument: TValue): TValue;
                begin
                Result := fSubContainer.Kernel.Resolver.Resolve(context, dependency, argument);
                end;

                procedure ScenarioOne;
                var
                c1, c2: TContainer;
                b: TBar;
                begin
                c1 := TContainer.Create;
                c2 := TContainer.Create;
                c1.Kernel.Resolver.AddSubResolver(TSubContainerResolver.Create(c1, c2));

                // dependency in subcontainer
                c1.RegisterType<TBar>;
                c1.Build;
                c2.RegisterType<TFoo>;
                c2.Build;

                b := c1.Resolve<TBar>;
                Assert(Assigned(b.fFoo));
                end;

                procedure ScenarioTwo;
                var
                c1, c2: TContainer;
                b: TBar;
                begin
                c1 := TContainer.Create;
                c2 := TContainer.Create;

                c1.Kernel.Resolver.AddSubResolver(TSubContainerResolver.Create(c1, c2));
                c2.Kernel.Resolver.AddSubResolver(TSubContainerResolver.Create(c2, c1));

                // type in subcontainer but dependency in parent container
                c1.RegisterType<TFoo>;
                c1.Build;
                c2.RegisterType<TBar>;
                c2.Build;

                b := c1.Resolve<TBar>;
                Assert(Assigned(b.fFoo));
                end;

                begin
                ScenarioOne;
                ScenarioTwo;
                end.





                share|improve this answer















                There are so called subdependency resolvers (future versions will just call them type resolver) inside a container that handle specific types or type patterns (like being able to resolve TArray<T> or IList<T> where T is something being registered).



                You can implement your own that checks if a type is not inside of the container you attached this resolver to and then delegate the resolve chain for this type to another container.



                Here is some example code how to achieve that (without freeing objects)



                uses
                Spring,
                Spring.Container,
                Spring.Container.Core,
                System.SysUtils;

                type
                TFoo = class

                end;

                TBar = class
                private
                fFoo: TFoo;
                public
                constructor Create(const foo: TFoo);
                property Foo: TFoo read fFoo;
                end;

                TSubContainerResolver = class(TInterfacedObject, ISubDependencyResolver)
                private
                fContainer: TContainer;
                fSubContainer: TContainer;
                public
                constructor Create(const container, subContainer: TContainer);

                function CanResolve(const context: ICreationContext;
                const dependency: TDependencyModel; const argument: TValue): Boolean;
                function Resolve(const context: ICreationContext;
                const dependency: TDependencyModel; const argument: TValue): TValue;
                end;

                TBar

                constructor TBar.Create(const foo: TFoo);
                begin
                fFoo := foo;
                end;

                TSubContainerResolver

                constructor TSubContainerResolver.Create(const container, subContainer: TContainer);
                begin
                fContainer := container;
                fSubContainer := subContainer;
                end;

                function TSubContainerResolver.CanResolve(const context: ICreationContext;
                const dependency: TDependencyModel; const argument: TValue): Boolean;
                begin
                Result := not fContainer.Kernel.Registry.HasService(dependency.TypeInfo)
                and fSubContainer.Kernel.Resolver.CanResolve(context, dependency, argument);
                end;

                function TSubContainerResolver.Resolve(const context: ICreationContext;
                const dependency: TDependencyModel; const argument: TValue): TValue;
                begin
                Result := fSubContainer.Kernel.Resolver.Resolve(context, dependency, argument);
                end;

                procedure ScenarioOne;
                var
                c1, c2: TContainer;
                b: TBar;
                begin
                c1 := TContainer.Create;
                c2 := TContainer.Create;
                c1.Kernel.Resolver.AddSubResolver(TSubContainerResolver.Create(c1, c2));

                // dependency in subcontainer
                c1.RegisterType<TBar>;
                c1.Build;
                c2.RegisterType<TFoo>;
                c2.Build;

                b := c1.Resolve<TBar>;
                Assert(Assigned(b.fFoo));
                end;

                procedure ScenarioTwo;
                var
                c1, c2: TContainer;
                b: TBar;
                begin
                c1 := TContainer.Create;
                c2 := TContainer.Create;

                c1.Kernel.Resolver.AddSubResolver(TSubContainerResolver.Create(c1, c2));
                c2.Kernel.Resolver.AddSubResolver(TSubContainerResolver.Create(c2, c1));

                // type in subcontainer but dependency in parent container
                c1.RegisterType<TFoo>;
                c1.Build;
                c2.RegisterType<TBar>;
                c2.Build;

                b := c1.Resolve<TBar>;
                Assert(Assigned(b.fFoo));
                end;

                begin
                ScenarioOne;
                ScenarioTwo;
                end.






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Sep 27 '17 at 18:10

























                answered Sep 25 '17 at 11:06









                Stefan GlienkeStefan Glienke

                16.2k13378




                16.2k13378



























                    draft saved

                    draft discarded
















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid


                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.

                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f46384964%2fhow-to-delegate-container1-resolvet-to-container2-resolvet-if-container1-ca%23new-answer', 'question_page');

                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    How to how show current date and time by default on contact form 7 in WordPress without taking input from user in datetimepicker

                    Darth Vader #20

                    Ondo