private ValidationResult ValidateInternal(string[] ruleSets) { var result = new ValidationResult { IsValid = true }; var binderPropsOrFieldsOfT = this.TypeProperties.Keys; foreach (var rule in ruleSets) { var strictMode = Faker.DefaultStrictMode; this.StrictModes.TryGetValue(rule, out strictMode); //If strictMode is not enabled, skip and move on to the next ruleSet. if (!strictMode) { continue; } //Otherwise, we need to take a diff of what the user //specified and what the Binder found reflecting over //type T. this.Ignores.TryGetValue(rule, out HashSet <string> ignores); this.Actions.TryGetValue(rule, out var populateActions); var userSet = new HashSet <string>(StringComparer.OrdinalIgnoreCase); if (ignores != null) { userSet.UnionWith(ignores); } if (populateActions != null) { userSet.UnionWith(populateActions.Keys); } //Get the set properties or fields that are only //known to the binder, while removing //items in userSet that are known to both the user and binder. userSet.SymmetricExceptWith(binderPropsOrFieldsOfT); //What's left in userSet is the set of properties or fields //that the user does not know about + .Rule() methods. if (userSet.Count > 0) { foreach (var propOrFieldOfT in userSet) { if (populateActions.TryGetValue(propOrFieldOfT, out var populateAction)) { // Very much a .Rules() action if (populateAction.ProhibtInStrictMode) { result.ExtraMessages.Add( $"When StrictMode is set to True the Faker<{typeof(T).Name}>.Rules(...) method cannot verify that all properties have rules. You need to use Faker<{typeof(T).Name}>.RuleFor( x => x.Prop, ...) for each property to ensure each property has an associated rule when StrictMode is true; otherwise, set StrictMode to False in order to use Faker<{typeof(T).Name}>.Rules() method."); result.IsValid = false; } } else //The user doesn't know about this property or field. Log it as a validation error. { result.MissingRules.Add(propOrFieldOfT); result.IsValid = false; } } } } return(result); }
/// <summary> /// Given an instance of T, populate it with the desired rule sets. /// </summary> protected virtual void PopulateInternal(T instance, string[] ruleSets) { ValidationResult vr = null; if (!IsValid.HasValue) { //run validation vr = ValidateInternal(ruleSets); this.IsValid = vr.IsValid; } if (!IsValid.GetValueOrDefault()) { throw MakeValidationException(vr ?? ValidateInternal(ruleSets)); } var typeProps = TypeProperties; lock (Randomizer.Locker.Value) { //Issue 57 - Make sure you generate a new context // before executing any rules. //Issue 143 - If the FakerHub doesn't have any context // (eg NewContext() has never been called), then call it // so we can increment IndexGlobal and IndexFaker. if (!this.FakerHub.HasContext) { FakerHub.NewContext(); } foreach (var ruleSet in ruleSets) { if (this.Actions.TryGetValue(ruleSet, out var populateActions)) { foreach (var action in populateActions.Values) { typeProps.TryGetValue(action.PropertyName, out MemberInfo member); var valueFactory = action.Action; if (valueFactory is null) { continue; // An .Ignore() rule. } if (member != null) { var prop = member as PropertyInfo; prop?.SetValue(instance, valueFactory(FakerHub, instance), null); var field = member as FieldInfo; field?.SetValue(instance, valueFactory(FakerHub, instance)); } else // member would be null if this was an RuleForObject. { //Invoke this if this is a basic rule which does not select a property or a field. var outputValue = valueFactory(FakerHub, instance); } } } } foreach (var ruleSet in ruleSets) { if (this.FinalizeActions.TryGetValue(ruleSet, out FinalizeAction <T> finalizer)) { finalizer.Action(this.FakerHub, instance); } } } }