示例#1
0
        private static ViewCheckResult BuildCheckResult(object view, List <ApiErrorView> errors, List <ApiErrorView> innerErrors)
        {
            var hasErrors      = errors.Any();
            var hasInnerErrors = innerErrors.Any();

            if (!hasInnerErrors && !hasErrors)
            {
                return(ViewCheckResult.Ok());
            }

            var allErrors = new List <ApiErrorView>(errors);

            if (hasInnerErrors)
            {
                allErrors.Add(ApiErrorViewFactory.InnerErrors(view, innerErrors));
            }

            return(ViewCheckResult.Error(ApiErrorViewFactory.InnerErrors(view, allErrors)));
        }
示例#2
0
        public static ViewCheckResult CheckAsView(this object view)
        {
            var type = view.GetType();
            var list = view as IList;

            if (list != null && type.IsConstructedGenericType)
            {
                var checkResults = (from object item in list select CheckAsView(item)).ToList();
                if (!checkResults.Any())
                {
                    return(ViewCheckResult.Ok());
                }

                var errorViews = checkResults
                                 .Where(result => !result.IsCorrect)
                                 .Select(result => result.ApiErrorView)
                                 .ToList();

                return(ViewCheckResult.Error(ApiErrorViewFactory.InnerErrors(view, errorViews)));
            }
            return(ViewChecker.CheckContract(view));
        }
示例#3
0
        /// <summary>
        ///     Checks if view complies with it's contract
        /// </summary>
        /// <param name="view">Object to check</param>
        /// <returns>Simply ok or verbose contract errors description (for reading, not serializing)</returns>
        /// <exception cref="InvalidOperationException">
        ///     Will be thrown if <see cref="view"/> does not have <see cref="ApiViewAttribute"/> attribute
        /// </exception>
        public static ViewCheckResult CheckContract(object view)
        {
            if (view == null)
            {
                return(ViewCheckResult.Ok());
            }

            if (!view.IsApiView())
            {
                throw new InvalidOperationException("No classes except API views can have contracts");
            }

            try
            {
                var properties        = view.GetType().GetRuntimeProperties();
                var checkResults      = new List <ApiErrorView>();
                var innerCheckResults = new List <ApiErrorView>();

                checkResults.AddRange(PerformSpecificChecks(view));

                foreach (var propertyInfo in properties)
                {
                    var propertyValue = propertyInfo.GetValue(view);

                    if (propertyValue != null)
                    {
                        if (propertyValue.IsApiView())
                        {
                            var checkResult = CheckContract(propertyValue);
                            if (!checkResult.IsCorrect)
                            {
                                innerCheckResults.Add(checkResult.ApiErrorView);
                            }
                        }
                        if (propertyValue.IsApiViewList())
                        {
                            var list = propertyValue as IList;
                            if (list == null)
                            {
                                continue;
                            }
                            innerCheckResults.AddRange(from object item in list
                                                       select CheckContract(item)
                                                       into checkResult
                                                       where !checkResult.IsCorrect
                                                       select checkResult.ApiErrorView);
                        }
                    }

                    var contractAttributes = propertyInfo.GetCustomAttributes <ApiContractAttribute>().ToList();
                    if (!contractAttributes.Any())
                    {
                        continue;
                    }

                    if (contractAttributes.Count != 1)
                    {
                        return(ViewCheckResult.Error(ApiErrorViewFactory.Unspecified()));
                    }

                    var contractAttribute = contractAttributes[0];
                    var contractType      = contractAttribute.Type;

                    var failedChecks = CheckerDictionary
                                       .Where(kv => contractType.HasFlag(kv.Key) && !kv.Value.Invoke(propertyValue))
                                       .Select(kv => kv.Key)
                                       .ToList();

                    if (failedChecks.Any())
                    {
                        var propertyName = propertyInfo.Name;
                        checkResults.AddRange(
                            failedChecks.Select(fc => ApiErrorViewFactory.ViewPropertyContractViolation(view, propertyName, fc)));
                    }
                }
                return(BuildCheckResult(view, checkResults, innerCheckResults));
            }
            catch (Exception ex)
            {
                return(ViewCheckResult.Error(ApiErrorViewFactory.Unspecified($"Failed to check view: {ex.Message}")));
            }
        }