Domain Driven Design: Accessing a configured value from an object without using a service locator

I have a User object that has a HasCompletedSecurity property that indicates whether that particular User answered the number of security questions required by the system. The number of security issues required by the system is configured and retrieved from the configuration file. How does the User class access configured information?

I currently have an IConfigurationService interface behind which I have implementations that use the equivalent of ConfigurationManager or Azure, if available. I encapsulated access to my DI container through the static InjectionService class, and currently I am allowing the configured value as follows:

 public class User { private static readonly IConfigurationService _configurationService = InjectionService.Resolve<IConfigurationService>(); public bool HasCompletedSecurity { get { // Uses the static _configurationService to get the // configured value: int numberOfRequiredResponses = GetConfiguredNumberOfRequiredResponses(); return this.SecurityQuestionResponses.Count() >= GetConfiguredNumberOfRequiredResponses(); } } } 

This, of course, is an example of the ServiceLocator antivirus template , and I don't like it. Static dependency makes unit testing anything that uses this class inconveniently.

I use the Entity Framework and take a replica from here I don’t want to pass my entities through the DI container to give their dependencies, so ... how do I access the configured value?

Change With this one-sided example (and I appreciate the suggestions for the right architecture for it), the more important question that interests me is the static links to services from entities? Is the answer simply an architect of entities in a way that you never need?

+7
source share
2 answers

Here, how would I define the User class:

 public class User { public bool HasCompletedSecurity { get; set; } // other members... } 

Seriously, this is the best solution because it separates the value by time dimension . Consider this: if a user completed all of the security issues in 2010, and you later change the business rule, will you deny the status of an existing user?

In most cases, it would probably be wiser to write down and persist in the fact that once in the past the user followed the security procedure that was in effect at that time. This way you do not bother existing users.

+5
source

You can still use the concept for Inversion of Control without using any IoC container or using it in the constructor of your object. I would approach this using a quasi-strategy template and would have something like:

 public interface ISecurityPolicy { public int MinimumSecurityQuestionResponses { get; } } public class User { public void HasCompletedSecurity (ISecurityPolicy security_policy) { return this.SecurityQuestionResponses.Count() >= security_policy.MinimumSecurityQuestionResponses; } } 

This puts the burden of providing a specific security policy that the user must satisfy for the caller, not the User class itself.

From now on, you can specify an additional parameter that you want, perhaps wrap it in an IUserSecurityService that will have ISecurityPolicy entered into the service, etc.

This is still Inversion of Control, but it is at the method level, as this one method is really the only one that cares about the security / configuration policy.

+1
source

All Articles