Reputation: 158
Firstly, thank you- I have become a better programmer by being "forced to" by Simple Injector.
Very early in the bootstrap of my program I setup my root container and shortly afterward call container.Verify()
Many of my services take a dependency on (my class) ICurrentUser
which has methods to retrieve account secrets and configuration. As would be expected these secret are available only after the user has authenticated, which has not occurred during the bootstrapping and call container.Verify()
.
example:
private readonly string serviceAccount;
public SomeService(ICurrentUser currentUser) {
serviceAccount = currentUser.GetSecret("SomeServiceAccount");
}
This has caused me to change the above to:
private Lazy<string> serviceAccount;
public SomeService(ICurrentUser currentUser) {
serviceAccount =
new Lazy<string>(() => currentUser.GetSecret("SomeServiceAccount"));
}
and then refer to serviceAccount.Value when it is needed. This seems a bit awkward and complicates the ctor. Alternatively I could postpone the verify until after the user authenticates but I don't really like that as it postpones what should happen after setting up the ctor.
Is there a way for me to split the verify process into an initial lightweight verification of the service relationships but not execute the constructors until a later step?
Upvotes: 0
Views: 49
Reputation: 172826
Constructors should be free of any logic, other than doing precondition checks and storing incoming dependencies, as explained here by Mark Seemann. This means that you should not make any calls to injected dependencies from inside the constructor, because:
The solution to this problem simply is to store the incoming ICurrentUser
dependency in the SomeService
class, and only call its GetSecret
method when one of SomeService
's methods are invoked.
You might be tempted to make loading of the value lazy, especially to prevent having to load it over and over again, which can happen if GetSecret
is called many times throughout the lifetime of SomeService
.
You should, however, refrain from implementing caching at that level, because that would complicate SomeService
and all other consumers of ICurrentUser
. Instead, you should either implement caching inside the ICurrentUser
implementation -or- wrap the implementation in a Decorator that adds the caching behavior. Registering decorators in Simple Injector is trivial.
Upvotes: 1