How to use dependency injection and avoid temporal coupling?Are init() methods a code smell?How does dependecy injection increase coupling?Reducing dependency cycles and reducing couplingHow can I avoid tight coupling when practically every decision-logic has to check lots of distributed state?Qualified dependency injection and couplingHow to prevent dependency injection from killing object oriented programmingDependency injection for a library with internal dependenciesHandling disposables with dependency injectionHow best to avoid member implementation of class' Abstract/Interface instance variables

Would a physician with migraine better treat their patients?

Is the value of a probability density function for a given input a point, a range, or both?

Making part of lines layer transparent based on circle

What is the word for things that work even when they aren't working (e.g. escalators)?

Why is it popular to teach modulus via the example of mod 12 and analogue clocks?

Why are seats at the rear of a plane sometimes unavailable even though many other seats are available in the plane?

What does the British parliament hope to achieve by requesting a third Brexit extension?

Does my code handle negative numbers or zero when summing squared digits?

What's the current zodiac?

Rationalism and Catholicism / Protestantism

Giving a character trauma but not "diagnosing" her?

Appending to each string in a list with mapping

Equation with indices at end and to right side

Pass a bash variable to python script

What is the German word for: "It only works when I try to show you how it does not work"?

Can a character dodge an attack that beats their Armor Class?

d-Menthol vs dl-menthol: Does an enantiomer and its racemic mixture have different melting points?

How safe is using non-RoHS parts?

What is the purpose of the redundant "いい人" in this example sentence

Legality of creating a SE replica using SE's content

How can a "proper" function have a vertical slope?

'provocative' vs 'sexy'

Why does this route work with a slash and not a dash?

Dynamics m, r, s, and z. What do they mean?



How to use dependency injection and avoid temporal coupling?


Are init() methods a code smell?How does dependecy injection increase coupling?Reducing dependency cycles and reducing couplingHow can I avoid tight coupling when practically every decision-logic has to check lots of distributed state?Qualified dependency injection and couplingHow to prevent dependency injection from killing object oriented programmingDependency injection for a library with internal dependenciesHandling disposables with dependency injectionHow best to avoid member implementation of class' Abstract/Interface instance variables






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty
margin-bottom:0;









11

















Suppose I have the Service that receives dependencies via constructor but also needs to be initialized with custom data (context) before it can be used:



public interface IService

void Initialize(Context context);
void DoSomething();
void DoOtherThing();


public class Service : IService

private readonly object dependency1;
private readonly object dependency2;
private readonly object dependency3;

public Service(
object dependency1,
object dependency2,
object dependency3)

this.dependency1 = dependency1 ?? throw new ArgumentNullException(nameof(dependency1));
this.dependency2 = dependency2 ?? throw new ArgumentNullException(nameof(dependency2));
this.dependency3 = dependency3 ?? throw new ArgumentNullException(nameof(dependency3));


public void Initialize(Context context)

// Initialize state based on context
// Heavy, long running operation


public void DoSomething()

// ...


public void DoOtherThing()

// ...



public class Context

public int Value1;
public string Value2;
public string Value3;



Now - the context data is not know beforehand so I cannot register it as a dependency and use DI to inject it into the service



This is how example client looks like:



public class Client

private readonly IService service;

public Client(IService service)

this.service = service ?? throw new ArgumentNullException(nameof(service));


public void OnStartup()

service.Initialize(new Context

Value1 = 123,
Value2 = "my data",
Value3 = "abcd"
);


public void Execute()

service.DoSomething();
service.DoOtherThing();




As you can see - there are temporal coupling and initialize method code smells involved, because I first need to call service.Initialize to be able to call service.DoSomething and service.DoOtherThing afterwards.



What are the other approaches in which I can eliminate these problems?



Additional clarification of the behavior:



Each instance of the client needs to have it's own instance of the service initialized with client's specific context data. So, that context data is not static or known in advance so it cannot be injected by DI in the constructor.










share|improve this question


































    11

















    Suppose I have the Service that receives dependencies via constructor but also needs to be initialized with custom data (context) before it can be used:



    public interface IService

    void Initialize(Context context);
    void DoSomething();
    void DoOtherThing();


    public class Service : IService

    private readonly object dependency1;
    private readonly object dependency2;
    private readonly object dependency3;

    public Service(
    object dependency1,
    object dependency2,
    object dependency3)

    this.dependency1 = dependency1 ?? throw new ArgumentNullException(nameof(dependency1));
    this.dependency2 = dependency2 ?? throw new ArgumentNullException(nameof(dependency2));
    this.dependency3 = dependency3 ?? throw new ArgumentNullException(nameof(dependency3));


    public void Initialize(Context context)

    // Initialize state based on context
    // Heavy, long running operation


    public void DoSomething()

    // ...


    public void DoOtherThing()

    // ...



    public class Context

    public int Value1;
    public string Value2;
    public string Value3;



    Now - the context data is not know beforehand so I cannot register it as a dependency and use DI to inject it into the service



    This is how example client looks like:



    public class Client

    private readonly IService service;

    public Client(IService service)

    this.service = service ?? throw new ArgumentNullException(nameof(service));


    public void OnStartup()

    service.Initialize(new Context

    Value1 = 123,
    Value2 = "my data",
    Value3 = "abcd"
    );


    public void Execute()

    service.DoSomething();
    service.DoOtherThing();




    As you can see - there are temporal coupling and initialize method code smells involved, because I first need to call service.Initialize to be able to call service.DoSomething and service.DoOtherThing afterwards.



    What are the other approaches in which I can eliminate these problems?



    Additional clarification of the behavior:



    Each instance of the client needs to have it's own instance of the service initialized with client's specific context data. So, that context data is not static or known in advance so it cannot be injected by DI in the constructor.










    share|improve this question






























      11












      11








      11


      1






      Suppose I have the Service that receives dependencies via constructor but also needs to be initialized with custom data (context) before it can be used:



      public interface IService

      void Initialize(Context context);
      void DoSomething();
      void DoOtherThing();


      public class Service : IService

      private readonly object dependency1;
      private readonly object dependency2;
      private readonly object dependency3;

      public Service(
      object dependency1,
      object dependency2,
      object dependency3)

      this.dependency1 = dependency1 ?? throw new ArgumentNullException(nameof(dependency1));
      this.dependency2 = dependency2 ?? throw new ArgumentNullException(nameof(dependency2));
      this.dependency3 = dependency3 ?? throw new ArgumentNullException(nameof(dependency3));


      public void Initialize(Context context)

      // Initialize state based on context
      // Heavy, long running operation


      public void DoSomething()

      // ...


      public void DoOtherThing()

      // ...



      public class Context

      public int Value1;
      public string Value2;
      public string Value3;



      Now - the context data is not know beforehand so I cannot register it as a dependency and use DI to inject it into the service



      This is how example client looks like:



      public class Client

      private readonly IService service;

      public Client(IService service)

      this.service = service ?? throw new ArgumentNullException(nameof(service));


      public void OnStartup()

      service.Initialize(new Context

      Value1 = 123,
      Value2 = "my data",
      Value3 = "abcd"
      );


      public void Execute()

      service.DoSomething();
      service.DoOtherThing();




      As you can see - there are temporal coupling and initialize method code smells involved, because I first need to call service.Initialize to be able to call service.DoSomething and service.DoOtherThing afterwards.



      What are the other approaches in which I can eliminate these problems?



      Additional clarification of the behavior:



      Each instance of the client needs to have it's own instance of the service initialized with client's specific context data. So, that context data is not static or known in advance so it cannot be injected by DI in the constructor.










      share|improve this question
















      Suppose I have the Service that receives dependencies via constructor but also needs to be initialized with custom data (context) before it can be used:



      public interface IService

      void Initialize(Context context);
      void DoSomething();
      void DoOtherThing();


      public class Service : IService

      private readonly object dependency1;
      private readonly object dependency2;
      private readonly object dependency3;

      public Service(
      object dependency1,
      object dependency2,
      object dependency3)

      this.dependency1 = dependency1 ?? throw new ArgumentNullException(nameof(dependency1));
      this.dependency2 = dependency2 ?? throw new ArgumentNullException(nameof(dependency2));
      this.dependency3 = dependency3 ?? throw new ArgumentNullException(nameof(dependency3));


      public void Initialize(Context context)

      // Initialize state based on context
      // Heavy, long running operation


      public void DoSomething()

      // ...


      public void DoOtherThing()

      // ...



      public class Context

      public int Value1;
      public string Value2;
      public string Value3;



      Now - the context data is not know beforehand so I cannot register it as a dependency and use DI to inject it into the service



      This is how example client looks like:



      public class Client

      private readonly IService service;

      public Client(IService service)

      this.service = service ?? throw new ArgumentNullException(nameof(service));


      public void OnStartup()

      service.Initialize(new Context

      Value1 = 123,
      Value2 = "my data",
      Value3 = "abcd"
      );


      public void Execute()

      service.DoSomething();
      service.DoOtherThing();




      As you can see - there are temporal coupling and initialize method code smells involved, because I first need to call service.Initialize to be able to call service.DoSomething and service.DoOtherThing afterwards.



      What are the other approaches in which I can eliminate these problems?



      Additional clarification of the behavior:



      Each instance of the client needs to have it's own instance of the service initialized with client's specific context data. So, that context data is not static or known in advance so it cannot be injected by DI in the constructor.







      dependency-injection coupling






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question



      share|improve this question








      edited May 2 at 12:50







      Dusan

















      asked May 2 at 12:24









      DusanDusan

      3203 silver badges19 bronze badges




      3203 silver badges19 bronze badges























          5 Answers
          5






          active

          oldest

          votes


















          17


















          There are several ways to deal with the initialization problem:



          • As answered in https://softwareengineering.stackexchange.com/a/334994/301401, init() methods are a code smell. Initializing an object is the responsibility of the constructor - that's why we have constructors after all.

          • Add The given service must be initialized to the doc comment of Client constructor and let the constructor throw if the service is not initialized. This moves the responsibility to the one who gives you the IService object.

          However, in your example, the Client is the only one that knows the values that are passed to Initialize(). If you want to keep it that way, I'd suggest the following:



          • Add an IServiceFactory and pass it to the Client constructor. Then you can call serviceFactory.createService(new Context(...)) which gives you an initialized IService that can be used by your client.

          The factories can be very simple and also allow you to avoid init() methods and use constructors instead:



          public interface IServiceFactory

          IService createService(Context context);


          public class ServiceFactory : IServiceFactory

          public Service createService(Context context)

          return new Service(context);




          In the client, OnStartup() is also an initialization method (it just uses a different name). So if possible (if you know the Context data), the factory should directly be called in the Client constructor. If that's not possible, you need to store the IServiceFactory and call it in OnStartup().



          When Service has dependencies not provided by Client they would be provided by DI through ServiceFactory:



          public interface IServiceFactory

          IService createService(Context context);


          public class ServiceFactory : IServiceFactory

          private readonly object dependency1;
          private readonly object dependency2;
          private readonly object dependency3;

          public ServiceFactory(object dependency1, object dependency2, object dependency3)

          this.dependency1 = dependency1;
          this.dependency2 = dependency2;
          this.dependency3 = dependency3;


          public Service createService(Context context)

          return new Service(context, dependency1, dependency2, dependency3);







          share|improve this answer























          • 1





            Thank you, just like I thought, in the last point... And in the ServiceFactory, would you use the constructor DI in the factory itself for the dependencies needed for the service constructor or the service locator would be more suitable?

            – Dusan
            May 2 at 12:58







          • 1





            @Dusan don't use Service Locator. If Service has dependencies other than the Context, that would not be provided by the Client, they can be provided via DI to the ServiceFactory to be passed to the Service when createService is called.

            – Mr.Mindor
            May 2 at 19:53











          • @Dusan If you need to supply different dependencies to different Services (ie: this one needs dependency1_1 but the next one needs dependency1_2), but if this pattern otherwise works for you, then you can use a similar pattern often called a Builder pattern. A Builder allows you to set up an object piecemeal over time if necessary. Then you can do this... ServiceBuilder partial = new ServiceBuilder().dependency1(dependency1_1).dependency2(dependency2_1).dependency3(dependency3_1); and be left with your partially set up service, then later do Service s = partial.context(context).build()

            – Aaron
            May 2 at 23:00


















          1


















          The Initialize method should be removed from the IService interface, as this is an implementation detail. Instead, define another class that takes the concrete instance of Service and calls the initialize method on it. Then this new class implements the IService interface:



          public class ContextDependentService : IService

          public ContextDependentService(Context context, Service service)

          this.service = service;

          service.Initialize(context);


          // Methods in the IService interface



          This keeps client code ignorant of the initialization procedure, except where the ContextDependentService class is initialized. You at least limit the parts of your application that need to know about this wonky initialization procedure.






          share|improve this answer

































            1


















            It seems to me that you have two options here



            1. Move the Initialisation code to the Context and inject an Initialised Context

            eg.



            public InitialisedContext Initialise()


            1. Have the first call to Execute call Initialise if its not allready done

            eg.



            public async Task Execute()

            //lock context
            //check context is not initialised
            // init if required
            //execute code...



            1. Just throw exceptions if Context isnt initialised when you call Execute. Like SqlConnection.

            Injecting a factory is fine if you just want to avoid passing context as a parameter. Say only this particular implementation needs a context and you want not to add it to the Interface



            But you essentially have the same problem, what if the factory hasn't got an initialised context yet.






            share|improve this answer



































              0


















              You should not depend your interface to any db context and initialize method. You can do it in concrete class constructor.



              public interface IService

              void DoSomething();
              void DoOtherThing();


              public class Service : IService

              private readonly object dependency1;
              private readonly object dependency2;
              private readonly object dependency3;
              private readonly object context;

              public Service(
              object dependency1,
              object dependency2,
              object dependency3,
              object context )

              this.dependency1 = dependency1 ?? throw new ArgumentNullException(nameof(dependency1));
              this.dependency2 = dependency2 ?? throw new ArgumentNullException(nameof(dependency2));
              this.dependency3 = dependency3 ?? throw new ArgumentNullException(nameof(dependency3));

              // context is concrete class details not interfaces.
              this.context = context;

              // call init here constructor.
              this.Initialize(context);


              protected void Initialize(Context context)

              // Initialize state based on context
              // Heavy, long running operation


              public void DoSomething()

              // ...


              public void DoOtherThing()

              // ...





              And, an answer of your main question would be Property Injection.



              public class Service

              public Service(Context context)

              this.context = context;


              private Dependency1 _dependency1;
              public Dependency1 Dependency1

              get

              if (_dependency1 == null)
              _dependency1 = Container.Resolve<Dependency1>();

              return _dependency1;



              //...




              This way you can call all dependencies by Property Injection. But it could be huge number. If so, you can use Constructor Injection for them, but you can set your context by property by checking if it is null.






              share|improve this answer




























              • OK, great, but... each instance of the client needs to have it's own instance of the service initialized with different context data. That context data is not static or known beforehand so it cannot be injected by DI in the constructor. Then, how do I get/create instance of the service together with other dependencies in my clients?

                – Dusan
                May 2 at 12:48











              • hmm wont that static constructor run before you set the context? and initialize in the constructor risks exceptions

                – Ewan
                May 2 at 12:49











              • I am leaning towards injecting factory that can create and initialize the service with the given context data (rather than injecting service itself), but I am not sure if there are better solutions.

                – Dusan
                May 2 at 12:54











              • @Ewan You are right. I will try to find a solution for it. But before that, I will remove it for now.

                – Engineert
                May 2 at 12:57


















              0


















              Misko Hevery has a very helpful blog post about the case you've faced. You both need newable and injectable for your Service class and this blog post may help you.






              share|improve this answer



























                Your Answer








                StackExchange.ready(function()
                var channelOptions =
                tags: "".split(" "),
                id: "131"
                ;
                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: false,
                noModals: true,
                showLowRepImageUploadWarning: true,
                reputationToPostImages: null,
                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/4.0/"u003ecc by-sa 4.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%2fsoftwareengineering.stackexchange.com%2fquestions%2f391290%2fhow-to-use-dependency-injection-and-avoid-temporal-coupling%23new-answer', 'question_page');

                );

                Post as a guest















                Required, but never shown


























                5 Answers
                5






                active

                oldest

                votes








                5 Answers
                5






                active

                oldest

                votes









                active

                oldest

                votes






                active

                oldest

                votes









                17


















                There are several ways to deal with the initialization problem:



                • As answered in https://softwareengineering.stackexchange.com/a/334994/301401, init() methods are a code smell. Initializing an object is the responsibility of the constructor - that's why we have constructors after all.

                • Add The given service must be initialized to the doc comment of Client constructor and let the constructor throw if the service is not initialized. This moves the responsibility to the one who gives you the IService object.

                However, in your example, the Client is the only one that knows the values that are passed to Initialize(). If you want to keep it that way, I'd suggest the following:



                • Add an IServiceFactory and pass it to the Client constructor. Then you can call serviceFactory.createService(new Context(...)) which gives you an initialized IService that can be used by your client.

                The factories can be very simple and also allow you to avoid init() methods and use constructors instead:



                public interface IServiceFactory

                IService createService(Context context);


                public class ServiceFactory : IServiceFactory

                public Service createService(Context context)

                return new Service(context);




                In the client, OnStartup() is also an initialization method (it just uses a different name). So if possible (if you know the Context data), the factory should directly be called in the Client constructor. If that's not possible, you need to store the IServiceFactory and call it in OnStartup().



                When Service has dependencies not provided by Client they would be provided by DI through ServiceFactory:



                public interface IServiceFactory

                IService createService(Context context);


                public class ServiceFactory : IServiceFactory

                private readonly object dependency1;
                private readonly object dependency2;
                private readonly object dependency3;

                public ServiceFactory(object dependency1, object dependency2, object dependency3)

                this.dependency1 = dependency1;
                this.dependency2 = dependency2;
                this.dependency3 = dependency3;


                public Service createService(Context context)

                return new Service(context, dependency1, dependency2, dependency3);







                share|improve this answer























                • 1





                  Thank you, just like I thought, in the last point... And in the ServiceFactory, would you use the constructor DI in the factory itself for the dependencies needed for the service constructor or the service locator would be more suitable?

                  – Dusan
                  May 2 at 12:58







                • 1





                  @Dusan don't use Service Locator. If Service has dependencies other than the Context, that would not be provided by the Client, they can be provided via DI to the ServiceFactory to be passed to the Service when createService is called.

                  – Mr.Mindor
                  May 2 at 19:53











                • @Dusan If you need to supply different dependencies to different Services (ie: this one needs dependency1_1 but the next one needs dependency1_2), but if this pattern otherwise works for you, then you can use a similar pattern often called a Builder pattern. A Builder allows you to set up an object piecemeal over time if necessary. Then you can do this... ServiceBuilder partial = new ServiceBuilder().dependency1(dependency1_1).dependency2(dependency2_1).dependency3(dependency3_1); and be left with your partially set up service, then later do Service s = partial.context(context).build()

                  – Aaron
                  May 2 at 23:00















                17


















                There are several ways to deal with the initialization problem:



                • As answered in https://softwareengineering.stackexchange.com/a/334994/301401, init() methods are a code smell. Initializing an object is the responsibility of the constructor - that's why we have constructors after all.

                • Add The given service must be initialized to the doc comment of Client constructor and let the constructor throw if the service is not initialized. This moves the responsibility to the one who gives you the IService object.

                However, in your example, the Client is the only one that knows the values that are passed to Initialize(). If you want to keep it that way, I'd suggest the following:



                • Add an IServiceFactory and pass it to the Client constructor. Then you can call serviceFactory.createService(new Context(...)) which gives you an initialized IService that can be used by your client.

                The factories can be very simple and also allow you to avoid init() methods and use constructors instead:



                public interface IServiceFactory

                IService createService(Context context);


                public class ServiceFactory : IServiceFactory

                public Service createService(Context context)

                return new Service(context);




                In the client, OnStartup() is also an initialization method (it just uses a different name). So if possible (if you know the Context data), the factory should directly be called in the Client constructor. If that's not possible, you need to store the IServiceFactory and call it in OnStartup().



                When Service has dependencies not provided by Client they would be provided by DI through ServiceFactory:



                public interface IServiceFactory

                IService createService(Context context);


                public class ServiceFactory : IServiceFactory

                private readonly object dependency1;
                private readonly object dependency2;
                private readonly object dependency3;

                public ServiceFactory(object dependency1, object dependency2, object dependency3)

                this.dependency1 = dependency1;
                this.dependency2 = dependency2;
                this.dependency3 = dependency3;


                public Service createService(Context context)

                return new Service(context, dependency1, dependency2, dependency3);







                share|improve this answer























                • 1





                  Thank you, just like I thought, in the last point... And in the ServiceFactory, would you use the constructor DI in the factory itself for the dependencies needed for the service constructor or the service locator would be more suitable?

                  – Dusan
                  May 2 at 12:58







                • 1





                  @Dusan don't use Service Locator. If Service has dependencies other than the Context, that would not be provided by the Client, they can be provided via DI to the ServiceFactory to be passed to the Service when createService is called.

                  – Mr.Mindor
                  May 2 at 19:53











                • @Dusan If you need to supply different dependencies to different Services (ie: this one needs dependency1_1 but the next one needs dependency1_2), but if this pattern otherwise works for you, then you can use a similar pattern often called a Builder pattern. A Builder allows you to set up an object piecemeal over time if necessary. Then you can do this... ServiceBuilder partial = new ServiceBuilder().dependency1(dependency1_1).dependency2(dependency2_1).dependency3(dependency3_1); and be left with your partially set up service, then later do Service s = partial.context(context).build()

                  – Aaron
                  May 2 at 23:00













                17














                17










                17









                There are several ways to deal with the initialization problem:



                • As answered in https://softwareengineering.stackexchange.com/a/334994/301401, init() methods are a code smell. Initializing an object is the responsibility of the constructor - that's why we have constructors after all.

                • Add The given service must be initialized to the doc comment of Client constructor and let the constructor throw if the service is not initialized. This moves the responsibility to the one who gives you the IService object.

                However, in your example, the Client is the only one that knows the values that are passed to Initialize(). If you want to keep it that way, I'd suggest the following:



                • Add an IServiceFactory and pass it to the Client constructor. Then you can call serviceFactory.createService(new Context(...)) which gives you an initialized IService that can be used by your client.

                The factories can be very simple and also allow you to avoid init() methods and use constructors instead:



                public interface IServiceFactory

                IService createService(Context context);


                public class ServiceFactory : IServiceFactory

                public Service createService(Context context)

                return new Service(context);




                In the client, OnStartup() is also an initialization method (it just uses a different name). So if possible (if you know the Context data), the factory should directly be called in the Client constructor. If that's not possible, you need to store the IServiceFactory and call it in OnStartup().



                When Service has dependencies not provided by Client they would be provided by DI through ServiceFactory:



                public interface IServiceFactory

                IService createService(Context context);


                public class ServiceFactory : IServiceFactory

                private readonly object dependency1;
                private readonly object dependency2;
                private readonly object dependency3;

                public ServiceFactory(object dependency1, object dependency2, object dependency3)

                this.dependency1 = dependency1;
                this.dependency2 = dependency2;
                this.dependency3 = dependency3;


                public Service createService(Context context)

                return new Service(context, dependency1, dependency2, dependency3);







                share|improve this answer
















                There are several ways to deal with the initialization problem:



                • As answered in https://softwareengineering.stackexchange.com/a/334994/301401, init() methods are a code smell. Initializing an object is the responsibility of the constructor - that's why we have constructors after all.

                • Add The given service must be initialized to the doc comment of Client constructor and let the constructor throw if the service is not initialized. This moves the responsibility to the one who gives you the IService object.

                However, in your example, the Client is the only one that knows the values that are passed to Initialize(). If you want to keep it that way, I'd suggest the following:



                • Add an IServiceFactory and pass it to the Client constructor. Then you can call serviceFactory.createService(new Context(...)) which gives you an initialized IService that can be used by your client.

                The factories can be very simple and also allow you to avoid init() methods and use constructors instead:



                public interface IServiceFactory

                IService createService(Context context);


                public class ServiceFactory : IServiceFactory

                public Service createService(Context context)

                return new Service(context);




                In the client, OnStartup() is also an initialization method (it just uses a different name). So if possible (if you know the Context data), the factory should directly be called in the Client constructor. If that's not possible, you need to store the IServiceFactory and call it in OnStartup().



                When Service has dependencies not provided by Client they would be provided by DI through ServiceFactory:



                public interface IServiceFactory

                IService createService(Context context);


                public class ServiceFactory : IServiceFactory

                private readonly object dependency1;
                private readonly object dependency2;
                private readonly object dependency3;

                public ServiceFactory(object dependency1, object dependency2, object dependency3)

                this.dependency1 = dependency1;
                this.dependency2 = dependency2;
                this.dependency3 = dependency3;


                public Service createService(Context context)

                return new Service(context, dependency1, dependency2, dependency3);








                share|improve this answer















                share|improve this answer




                share|improve this answer



                share|improve this answer








                edited May 2 at 21:40









                Mr.Mindor

                2992 silver badges8 bronze badges




                2992 silver badges8 bronze badges










                answered May 2 at 12:52









                pschillpschill

                4991 silver badge9 bronze badges




                4991 silver badge9 bronze badges










                • 1





                  Thank you, just like I thought, in the last point... And in the ServiceFactory, would you use the constructor DI in the factory itself for the dependencies needed for the service constructor or the service locator would be more suitable?

                  – Dusan
                  May 2 at 12:58







                • 1





                  @Dusan don't use Service Locator. If Service has dependencies other than the Context, that would not be provided by the Client, they can be provided via DI to the ServiceFactory to be passed to the Service when createService is called.

                  – Mr.Mindor
                  May 2 at 19:53











                • @Dusan If you need to supply different dependencies to different Services (ie: this one needs dependency1_1 but the next one needs dependency1_2), but if this pattern otherwise works for you, then you can use a similar pattern often called a Builder pattern. A Builder allows you to set up an object piecemeal over time if necessary. Then you can do this... ServiceBuilder partial = new ServiceBuilder().dependency1(dependency1_1).dependency2(dependency2_1).dependency3(dependency3_1); and be left with your partially set up service, then later do Service s = partial.context(context).build()

                  – Aaron
                  May 2 at 23:00












                • 1





                  Thank you, just like I thought, in the last point... And in the ServiceFactory, would you use the constructor DI in the factory itself for the dependencies needed for the service constructor or the service locator would be more suitable?

                  – Dusan
                  May 2 at 12:58







                • 1





                  @Dusan don't use Service Locator. If Service has dependencies other than the Context, that would not be provided by the Client, they can be provided via DI to the ServiceFactory to be passed to the Service when createService is called.

                  – Mr.Mindor
                  May 2 at 19:53











                • @Dusan If you need to supply different dependencies to different Services (ie: this one needs dependency1_1 but the next one needs dependency1_2), but if this pattern otherwise works for you, then you can use a similar pattern often called a Builder pattern. A Builder allows you to set up an object piecemeal over time if necessary. Then you can do this... ServiceBuilder partial = new ServiceBuilder().dependency1(dependency1_1).dependency2(dependency2_1).dependency3(dependency3_1); and be left with your partially set up service, then later do Service s = partial.context(context).build()

                  – Aaron
                  May 2 at 23:00







                1




                1





                Thank you, just like I thought, in the last point... And in the ServiceFactory, would you use the constructor DI in the factory itself for the dependencies needed for the service constructor or the service locator would be more suitable?

                – Dusan
                May 2 at 12:58






                Thank you, just like I thought, in the last point... And in the ServiceFactory, would you use the constructor DI in the factory itself for the dependencies needed for the service constructor or the service locator would be more suitable?

                – Dusan
                May 2 at 12:58





                1




                1





                @Dusan don't use Service Locator. If Service has dependencies other than the Context, that would not be provided by the Client, they can be provided via DI to the ServiceFactory to be passed to the Service when createService is called.

                – Mr.Mindor
                May 2 at 19:53





                @Dusan don't use Service Locator. If Service has dependencies other than the Context, that would not be provided by the Client, they can be provided via DI to the ServiceFactory to be passed to the Service when createService is called.

                – Mr.Mindor
                May 2 at 19:53













                @Dusan If you need to supply different dependencies to different Services (ie: this one needs dependency1_1 but the next one needs dependency1_2), but if this pattern otherwise works for you, then you can use a similar pattern often called a Builder pattern. A Builder allows you to set up an object piecemeal over time if necessary. Then you can do this... ServiceBuilder partial = new ServiceBuilder().dependency1(dependency1_1).dependency2(dependency2_1).dependency3(dependency3_1); and be left with your partially set up service, then later do Service s = partial.context(context).build()

                – Aaron
                May 2 at 23:00





                @Dusan If you need to supply different dependencies to different Services (ie: this one needs dependency1_1 but the next one needs dependency1_2), but if this pattern otherwise works for you, then you can use a similar pattern often called a Builder pattern. A Builder allows you to set up an object piecemeal over time if necessary. Then you can do this... ServiceBuilder partial = new ServiceBuilder().dependency1(dependency1_1).dependency2(dependency2_1).dependency3(dependency3_1); and be left with your partially set up service, then later do Service s = partial.context(context).build()

                – Aaron
                May 2 at 23:00













                1


















                The Initialize method should be removed from the IService interface, as this is an implementation detail. Instead, define another class that takes the concrete instance of Service and calls the initialize method on it. Then this new class implements the IService interface:



                public class ContextDependentService : IService

                public ContextDependentService(Context context, Service service)

                this.service = service;

                service.Initialize(context);


                // Methods in the IService interface



                This keeps client code ignorant of the initialization procedure, except where the ContextDependentService class is initialized. You at least limit the parts of your application that need to know about this wonky initialization procedure.






                share|improve this answer






























                  1


















                  The Initialize method should be removed from the IService interface, as this is an implementation detail. Instead, define another class that takes the concrete instance of Service and calls the initialize method on it. Then this new class implements the IService interface:



                  public class ContextDependentService : IService

                  public ContextDependentService(Context context, Service service)

                  this.service = service;

                  service.Initialize(context);


                  // Methods in the IService interface



                  This keeps client code ignorant of the initialization procedure, except where the ContextDependentService class is initialized. You at least limit the parts of your application that need to know about this wonky initialization procedure.






                  share|improve this answer




























                    1














                    1










                    1









                    The Initialize method should be removed from the IService interface, as this is an implementation detail. Instead, define another class that takes the concrete instance of Service and calls the initialize method on it. Then this new class implements the IService interface:



                    public class ContextDependentService : IService

                    public ContextDependentService(Context context, Service service)

                    this.service = service;

                    service.Initialize(context);


                    // Methods in the IService interface



                    This keeps client code ignorant of the initialization procedure, except where the ContextDependentService class is initialized. You at least limit the parts of your application that need to know about this wonky initialization procedure.






                    share|improve this answer














                    The Initialize method should be removed from the IService interface, as this is an implementation detail. Instead, define another class that takes the concrete instance of Service and calls the initialize method on it. Then this new class implements the IService interface:



                    public class ContextDependentService : IService

                    public ContextDependentService(Context context, Service service)

                    this.service = service;

                    service.Initialize(context);


                    // Methods in the IService interface



                    This keeps client code ignorant of the initialization procedure, except where the ContextDependentService class is initialized. You at least limit the parts of your application that need to know about this wonky initialization procedure.







                    share|improve this answer













                    share|improve this answer




                    share|improve this answer



                    share|improve this answer










                    answered May 2 at 12:57









                    Greg BurghardtGreg Burghardt

                    14.8k5 gold badges36 silver badges63 bronze badges




                    14.8k5 gold badges36 silver badges63 bronze badges
























                        1


















                        It seems to me that you have two options here



                        1. Move the Initialisation code to the Context and inject an Initialised Context

                        eg.



                        public InitialisedContext Initialise()


                        1. Have the first call to Execute call Initialise if its not allready done

                        eg.



                        public async Task Execute()

                        //lock context
                        //check context is not initialised
                        // init if required
                        //execute code...



                        1. Just throw exceptions if Context isnt initialised when you call Execute. Like SqlConnection.

                        Injecting a factory is fine if you just want to avoid passing context as a parameter. Say only this particular implementation needs a context and you want not to add it to the Interface



                        But you essentially have the same problem, what if the factory hasn't got an initialised context yet.






                        share|improve this answer
































                          1


















                          It seems to me that you have two options here



                          1. Move the Initialisation code to the Context and inject an Initialised Context

                          eg.



                          public InitialisedContext Initialise()


                          1. Have the first call to Execute call Initialise if its not allready done

                          eg.



                          public async Task Execute()

                          //lock context
                          //check context is not initialised
                          // init if required
                          //execute code...



                          1. Just throw exceptions if Context isnt initialised when you call Execute. Like SqlConnection.

                          Injecting a factory is fine if you just want to avoid passing context as a parameter. Say only this particular implementation needs a context and you want not to add it to the Interface



                          But you essentially have the same problem, what if the factory hasn't got an initialised context yet.






                          share|improve this answer






























                            1














                            1










                            1









                            It seems to me that you have two options here



                            1. Move the Initialisation code to the Context and inject an Initialised Context

                            eg.



                            public InitialisedContext Initialise()


                            1. Have the first call to Execute call Initialise if its not allready done

                            eg.



                            public async Task Execute()

                            //lock context
                            //check context is not initialised
                            // init if required
                            //execute code...



                            1. Just throw exceptions if Context isnt initialised when you call Execute. Like SqlConnection.

                            Injecting a factory is fine if you just want to avoid passing context as a parameter. Say only this particular implementation needs a context and you want not to add it to the Interface



                            But you essentially have the same problem, what if the factory hasn't got an initialised context yet.






                            share|improve this answer
















                            It seems to me that you have two options here



                            1. Move the Initialisation code to the Context and inject an Initialised Context

                            eg.



                            public InitialisedContext Initialise()


                            1. Have the first call to Execute call Initialise if its not allready done

                            eg.



                            public async Task Execute()

                            //lock context
                            //check context is not initialised
                            // init if required
                            //execute code...



                            1. Just throw exceptions if Context isnt initialised when you call Execute. Like SqlConnection.

                            Injecting a factory is fine if you just want to avoid passing context as a parameter. Say only this particular implementation needs a context and you want not to add it to the Interface



                            But you essentially have the same problem, what if the factory hasn't got an initialised context yet.







                            share|improve this answer















                            share|improve this answer




                            share|improve this answer



                            share|improve this answer








                            edited May 2 at 13:11

























                            answered May 2 at 12:54









                            EwanEwan

                            48.3k3 gold badges48 silver badges108 bronze badges




                            48.3k3 gold badges48 silver badges108 bronze badges
























                                0


















                                You should not depend your interface to any db context and initialize method. You can do it in concrete class constructor.



                                public interface IService

                                void DoSomething();
                                void DoOtherThing();


                                public class Service : IService

                                private readonly object dependency1;
                                private readonly object dependency2;
                                private readonly object dependency3;
                                private readonly object context;

                                public Service(
                                object dependency1,
                                object dependency2,
                                object dependency3,
                                object context )

                                this.dependency1 = dependency1 ?? throw new ArgumentNullException(nameof(dependency1));
                                this.dependency2 = dependency2 ?? throw new ArgumentNullException(nameof(dependency2));
                                this.dependency3 = dependency3 ?? throw new ArgumentNullException(nameof(dependency3));

                                // context is concrete class details not interfaces.
                                this.context = context;

                                // call init here constructor.
                                this.Initialize(context);


                                protected void Initialize(Context context)

                                // Initialize state based on context
                                // Heavy, long running operation


                                public void DoSomething()

                                // ...


                                public void DoOtherThing()

                                // ...





                                And, an answer of your main question would be Property Injection.



                                public class Service

                                public Service(Context context)

                                this.context = context;


                                private Dependency1 _dependency1;
                                public Dependency1 Dependency1

                                get

                                if (_dependency1 == null)
                                _dependency1 = Container.Resolve<Dependency1>();

                                return _dependency1;



                                //...




                                This way you can call all dependencies by Property Injection. But it could be huge number. If so, you can use Constructor Injection for them, but you can set your context by property by checking if it is null.






                                share|improve this answer




























                                • OK, great, but... each instance of the client needs to have it's own instance of the service initialized with different context data. That context data is not static or known beforehand so it cannot be injected by DI in the constructor. Then, how do I get/create instance of the service together with other dependencies in my clients?

                                  – Dusan
                                  May 2 at 12:48











                                • hmm wont that static constructor run before you set the context? and initialize in the constructor risks exceptions

                                  – Ewan
                                  May 2 at 12:49











                                • I am leaning towards injecting factory that can create and initialize the service with the given context data (rather than injecting service itself), but I am not sure if there are better solutions.

                                  – Dusan
                                  May 2 at 12:54











                                • @Ewan You are right. I will try to find a solution for it. But before that, I will remove it for now.

                                  – Engineert
                                  May 2 at 12:57















                                0


















                                You should not depend your interface to any db context and initialize method. You can do it in concrete class constructor.



                                public interface IService

                                void DoSomething();
                                void DoOtherThing();


                                public class Service : IService

                                private readonly object dependency1;
                                private readonly object dependency2;
                                private readonly object dependency3;
                                private readonly object context;

                                public Service(
                                object dependency1,
                                object dependency2,
                                object dependency3,
                                object context )

                                this.dependency1 = dependency1 ?? throw new ArgumentNullException(nameof(dependency1));
                                this.dependency2 = dependency2 ?? throw new ArgumentNullException(nameof(dependency2));
                                this.dependency3 = dependency3 ?? throw new ArgumentNullException(nameof(dependency3));

                                // context is concrete class details not interfaces.
                                this.context = context;

                                // call init here constructor.
                                this.Initialize(context);


                                protected void Initialize(Context context)

                                // Initialize state based on context
                                // Heavy, long running operation


                                public void DoSomething()

                                // ...


                                public void DoOtherThing()

                                // ...





                                And, an answer of your main question would be Property Injection.



                                public class Service

                                public Service(Context context)

                                this.context = context;


                                private Dependency1 _dependency1;
                                public Dependency1 Dependency1

                                get

                                if (_dependency1 == null)
                                _dependency1 = Container.Resolve<Dependency1>();

                                return _dependency1;



                                //...




                                This way you can call all dependencies by Property Injection. But it could be huge number. If so, you can use Constructor Injection for them, but you can set your context by property by checking if it is null.






                                share|improve this answer




























                                • OK, great, but... each instance of the client needs to have it's own instance of the service initialized with different context data. That context data is not static or known beforehand so it cannot be injected by DI in the constructor. Then, how do I get/create instance of the service together with other dependencies in my clients?

                                  – Dusan
                                  May 2 at 12:48











                                • hmm wont that static constructor run before you set the context? and initialize in the constructor risks exceptions

                                  – Ewan
                                  May 2 at 12:49











                                • I am leaning towards injecting factory that can create and initialize the service with the given context data (rather than injecting service itself), but I am not sure if there are better solutions.

                                  – Dusan
                                  May 2 at 12:54











                                • @Ewan You are right. I will try to find a solution for it. But before that, I will remove it for now.

                                  – Engineert
                                  May 2 at 12:57













                                0














                                0










                                0









                                You should not depend your interface to any db context and initialize method. You can do it in concrete class constructor.



                                public interface IService

                                void DoSomething();
                                void DoOtherThing();


                                public class Service : IService

                                private readonly object dependency1;
                                private readonly object dependency2;
                                private readonly object dependency3;
                                private readonly object context;

                                public Service(
                                object dependency1,
                                object dependency2,
                                object dependency3,
                                object context )

                                this.dependency1 = dependency1 ?? throw new ArgumentNullException(nameof(dependency1));
                                this.dependency2 = dependency2 ?? throw new ArgumentNullException(nameof(dependency2));
                                this.dependency3 = dependency3 ?? throw new ArgumentNullException(nameof(dependency3));

                                // context is concrete class details not interfaces.
                                this.context = context;

                                // call init here constructor.
                                this.Initialize(context);


                                protected void Initialize(Context context)

                                // Initialize state based on context
                                // Heavy, long running operation


                                public void DoSomething()

                                // ...


                                public void DoOtherThing()

                                // ...





                                And, an answer of your main question would be Property Injection.



                                public class Service

                                public Service(Context context)

                                this.context = context;


                                private Dependency1 _dependency1;
                                public Dependency1 Dependency1

                                get

                                if (_dependency1 == null)
                                _dependency1 = Container.Resolve<Dependency1>();

                                return _dependency1;



                                //...




                                This way you can call all dependencies by Property Injection. But it could be huge number. If so, you can use Constructor Injection for them, but you can set your context by property by checking if it is null.






                                share|improve this answer
















                                You should not depend your interface to any db context and initialize method. You can do it in concrete class constructor.



                                public interface IService

                                void DoSomething();
                                void DoOtherThing();


                                public class Service : IService

                                private readonly object dependency1;
                                private readonly object dependency2;
                                private readonly object dependency3;
                                private readonly object context;

                                public Service(
                                object dependency1,
                                object dependency2,
                                object dependency3,
                                object context )

                                this.dependency1 = dependency1 ?? throw new ArgumentNullException(nameof(dependency1));
                                this.dependency2 = dependency2 ?? throw new ArgumentNullException(nameof(dependency2));
                                this.dependency3 = dependency3 ?? throw new ArgumentNullException(nameof(dependency3));

                                // context is concrete class details not interfaces.
                                this.context = context;

                                // call init here constructor.
                                this.Initialize(context);


                                protected void Initialize(Context context)

                                // Initialize state based on context
                                // Heavy, long running operation


                                public void DoSomething()

                                // ...


                                public void DoOtherThing()

                                // ...





                                And, an answer of your main question would be Property Injection.



                                public class Service

                                public Service(Context context)

                                this.context = context;


                                private Dependency1 _dependency1;
                                public Dependency1 Dependency1

                                get

                                if (_dependency1 == null)
                                _dependency1 = Container.Resolve<Dependency1>();

                                return _dependency1;



                                //...




                                This way you can call all dependencies by Property Injection. But it could be huge number. If so, you can use Constructor Injection for them, but you can set your context by property by checking if it is null.







                                share|improve this answer















                                share|improve this answer




                                share|improve this answer



                                share|improve this answer








                                edited May 2 at 13:14

























                                answered May 2 at 12:40









                                EngineertEngineert

                                8111 gold badge3 silver badges16 bronze badges




                                8111 gold badge3 silver badges16 bronze badges















                                • OK, great, but... each instance of the client needs to have it's own instance of the service initialized with different context data. That context data is not static or known beforehand so it cannot be injected by DI in the constructor. Then, how do I get/create instance of the service together with other dependencies in my clients?

                                  – Dusan
                                  May 2 at 12:48











                                • hmm wont that static constructor run before you set the context? and initialize in the constructor risks exceptions

                                  – Ewan
                                  May 2 at 12:49











                                • I am leaning towards injecting factory that can create and initialize the service with the given context data (rather than injecting service itself), but I am not sure if there are better solutions.

                                  – Dusan
                                  May 2 at 12:54











                                • @Ewan You are right. I will try to find a solution for it. But before that, I will remove it for now.

                                  – Engineert
                                  May 2 at 12:57

















                                • OK, great, but... each instance of the client needs to have it's own instance of the service initialized with different context data. That context data is not static or known beforehand so it cannot be injected by DI in the constructor. Then, how do I get/create instance of the service together with other dependencies in my clients?

                                  – Dusan
                                  May 2 at 12:48











                                • hmm wont that static constructor run before you set the context? and initialize in the constructor risks exceptions

                                  – Ewan
                                  May 2 at 12:49











                                • I am leaning towards injecting factory that can create and initialize the service with the given context data (rather than injecting service itself), but I am not sure if there are better solutions.

                                  – Dusan
                                  May 2 at 12:54











                                • @Ewan You are right. I will try to find a solution for it. But before that, I will remove it for now.

                                  – Engineert
                                  May 2 at 12:57
















                                OK, great, but... each instance of the client needs to have it's own instance of the service initialized with different context data. That context data is not static or known beforehand so it cannot be injected by DI in the constructor. Then, how do I get/create instance of the service together with other dependencies in my clients?

                                – Dusan
                                May 2 at 12:48





                                OK, great, but... each instance of the client needs to have it's own instance of the service initialized with different context data. That context data is not static or known beforehand so it cannot be injected by DI in the constructor. Then, how do I get/create instance of the service together with other dependencies in my clients?

                                – Dusan
                                May 2 at 12:48













                                hmm wont that static constructor run before you set the context? and initialize in the constructor risks exceptions

                                – Ewan
                                May 2 at 12:49





                                hmm wont that static constructor run before you set the context? and initialize in the constructor risks exceptions

                                – Ewan
                                May 2 at 12:49













                                I am leaning towards injecting factory that can create and initialize the service with the given context data (rather than injecting service itself), but I am not sure if there are better solutions.

                                – Dusan
                                May 2 at 12:54





                                I am leaning towards injecting factory that can create and initialize the service with the given context data (rather than injecting service itself), but I am not sure if there are better solutions.

                                – Dusan
                                May 2 at 12:54













                                @Ewan You are right. I will try to find a solution for it. But before that, I will remove it for now.

                                – Engineert
                                May 2 at 12:57





                                @Ewan You are right. I will try to find a solution for it. But before that, I will remove it for now.

                                – Engineert
                                May 2 at 12:57











                                0


















                                Misko Hevery has a very helpful blog post about the case you've faced. You both need newable and injectable for your Service class and this blog post may help you.






                                share|improve this answer






























                                  0


















                                  Misko Hevery has a very helpful blog post about the case you've faced. You both need newable and injectable for your Service class and this blog post may help you.






                                  share|improve this answer




























                                    0














                                    0










                                    0









                                    Misko Hevery has a very helpful blog post about the case you've faced. You both need newable and injectable for your Service class and this blog post may help you.






                                    share|improve this answer














                                    Misko Hevery has a very helpful blog post about the case you've faced. You both need newable and injectable for your Service class and this blog post may help you.







                                    share|improve this answer













                                    share|improve this answer




                                    share|improve this answer



                                    share|improve this answer










                                    answered May 8 at 19:15









                                    Bold P.Bold P.

                                    243 bronze badges




                                    243 bronze badges































                                        draft saved

                                        draft discarded















































                                        Thanks for contributing an answer to Software Engineering Stack Exchange!


                                        • 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%2fsoftwareengineering.stackexchange.com%2fquestions%2f391290%2fhow-to-use-dependency-injection-and-avoid-temporal-coupling%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

                                        Distance measures on a map of a game The 2019 Stack Overflow Developer Survey Results Are Inmin distance in a graphShortest distance path on contour plotHow to plot a tilted map?Finding points outside of a diskDelaunay link distanceAnnulus from GeoDisks: drawing a ring on a mapNegative Correlation DistanceFind distance along a path (GPS coordinates)Finding position at given distance in a GeoPathMathematics behind distance estimation using camera

                                        How to get a smooth, uniform ParametricPlot of a 2D Region?How to plot a complicated Region?How to exclude a region from ParametricPlotHow discretize a region placing vertices on a specific non-uniform gridHow to transform a Plot or a ParametricPlot into a RegionHow can I get a smooth plot of a bounded region?Smooth ParametricPlot3D with RegionFunction?Smooth border of a region ParametricPlotSmooth region boundarySmooth region plot from list of pointsGet minimum y of a certain x in a region

                                        Genealogie vun de Merowenger Vum Merowech bis zum Chilperich I. | Navigatiounsmenü