Question

I have a Parent object which looks like this (pseudocode):

class Parent {
  String token;
  Child[] children;
}

It contains a token string and an array of Child objects. My problem is that each of these Child objects needs to access the token string from the Parent class.

My first hunch is to loop through the children and specifically set a reference to the Parent object. Is there a more recommended way to take care of this, or is this kind of coupling unavoidable? I'm working in C# specifically but would be interested in any language-agnostic solutions as well.

Was it helpful?

Solution

A reference to the parent in the child is one method. Another is (if the child's methods are being called by the parent) to pass the parent (or just the token) as a parameter where it's needed.

Factors that could affect the decision:

  • Is Parent mutable or immutable? Same question for Child.
  • Do children ever change parents, or is it fixed once constructed?
  • Are children ever shared between multiple parents?

OTHER TIPS

Depends on the problem. But scoped service containers can help here.

var serviceProvider = new ServiceCollection()
   .AddScoped<ITokenProvider, TokenProvider>()
   .AddTransiant<ISomething, ISomethingOne>()
   .AddTransiant<ISomething, ISomethingTwo>()
   .AddTransiant<ISomeUnitOfWork, SomeUnitOfWork>()
   .BuildServiceProvider();

using (var scope = serviceProvider.CreateScope())
{
   await scope.ServiceProvider.GetService<ISomeUnitOfWork>().Work();
}

Since ITokenProvider is scoped all services will get the same instance during the same scope.

So 

public class SomeUnitOfWork : ISomeUnitOfWork
{
   public SomeUnitOfWork(ITokenProvider tokenProvider, IEnumerable<ISomething> somethings)
   {
      this.tokenProvider = tokenProvider;
      this.somethings = somethings;
   }

   public Task Work() 
   {
      tokenProvider.SetToken("Foobar"); //This can be done anywere in the lifetime of the scope
      return somethings
         .Select(s => s.Execute())
         .WhenAll();
   }
}

public class SomethingOne : ISomething
{
   public SomethingOne(ITokenProvider tokenProvider) 
   {
      this.tokenProvider = tokenProvider;
   }

   public Task Execute() 
   {
      //TODO: Do some work
   }

}

Scopes are a really powerful tool in a large system. For example in a frontend each window can have its own scope. And events will be fired between components in the window them using a scoped event aggregator.

Some more info on my blog (Not using AspNetCore DI so a bit outdated) https://andersmalmgren.com/2015/06/23/abstract-di-container-scopes/

Licensed under: CC-BY-SA with attribution
scroll top