public IndexValidationVisitor(
            ModelStateDictionary modelState,
            IIndexModelValidatorProvider validatorProvider,
            IndexValidatorCache validatorCache,
            IModelMetadataProvider metadataProvider,
            ValidationStateDictionary validationState)
        {
            if (validatorProvider == null)
            {
                throw new ArgumentNullException(nameof(validatorProvider));
            }

            if (validatorCache == null)
            {
                throw new ArgumentNullException(nameof(validatorCache));
            }

            _validatorProvider = validatorProvider;
            _validatorCache    = validatorCache;

            _metadataProvider = metadataProvider;
            _validationState  = validationState;

            _modelState  = modelState;
            _currentPath = new ValidationStack();
        }
        private static CompositeIndexModelValidatorProvider CreateDefaultValidatorProvider()
        {
            var providers = new IIndexModelValidatorProvider[]
            {
                new DefaultIndexModelValidatorProvider()
            };

            return(new CompositeIndexModelValidatorProvider(providers));
        }
        public DefaultIndexObjectValidator(
            IModelMetadataProvider modelMetadataProvider,
            IList <IIndexModelValidatorProvider> validatorProviders)
        {
            if (modelMetadataProvider == null)
            {
                throw new ArgumentNullException(nameof(modelMetadataProvider));
            }

            if (validatorProviders == null)
            {
                throw new ArgumentNullException(nameof(validatorProviders));
            }

            _modelMetadataProvider = modelMetadataProvider;
            _validatorCache        = new IndexValidatorCache();

            _validatorProvider = new CompositeIndexModelValidatorProvider(validatorProviders);
        }
        private void ExecuteProvider(IIndexModelValidatorProvider validatorProvider, ModelMetadata metadata, List <IndexValidatorItem> items)
        {
            var context = new IndexModelValidatorProviderContext(metadata, items);

            validatorProvider.CreateValidators(context);
        }
        private IReadOnlyList <IIndexModelValidator> GetValidatorsFromEntry(CacheEntry entry, ModelMetadata metadata, IIndexModelValidatorProvider validationProvider)
        {
            Debug.Assert(entry.Validators != null || entry.Items != null);

            if (entry.Validators != null)
            {
                return(entry.Validators);
            }

            var items = new List <IndexValidatorItem>(entry.Items.Count);

            for (var i = 0; i < entry.Items.Count; i++)
            {
                var item = entry.Items[i];
                if (item.IsReusable)
                {
                    items.Add(item);
                }
                else
                {
                    items.Add(new IndexValidatorItem(item.ValidatorMetadata));
                }
            }

            ExecuteProvider(validationProvider, metadata, items);

            return(ExtractValidators(items));
        }
        public IReadOnlyList <IIndexModelValidator> GetValidators(ModelMetadata metadata, IIndexModelValidatorProvider validatorProvider)
        {
            CacheEntry entry;

            if (_cacheEntries.TryGetValue(metadata, out entry))
            {
                return(GetValidatorsFromEntry(entry, metadata, validatorProvider));
            }

            var items = new List <IndexValidatorItem>(metadata.ValidatorMetadata.Count);

            for (var i = 0; i < metadata.ValidatorMetadata.Count; i++)
            {
                items.Add(new IndexValidatorItem(metadata.ValidatorMetadata[i]));
            }

            ExecuteProvider(validatorProvider, metadata, items);

            var validators = ExtractValidators(items);

            var allValidatorsCached = true;

            for (var i = 0; i < items.Count; i++)
            {
                var item = items[i];
                if (!item.IsReusable)
                {
                    item.Validator      = null;
                    allValidatorsCached = false;
                }
            }

            if (allValidatorsCached)
            {
                entry = new CacheEntry(validators);
            }
            else
            {
                entry = new CacheEntry(items);
            }

            _cacheEntries.TryAdd(metadata, entry);

            return(validators);
        }