< Summary

Class:ReactiveUI.Validation.Extensions.ValidatableViewModelExtensions
Assembly:ReactiveUI.Validation
File(s):D:\a\1\s\src\ReactiveUI.Validation\Extensions\ValidatableViewModelExtensions.cs
Covered lines:32
Uncovered lines:67
Coverable lines:99
Total lines:402
Line coverage:32.3% (32 of 99)
Covered branches:13
Total branches:60
Branch coverage:21.6% (13 of 60)

Metrics

MethodCyclomatic complexity Line coverage Branch coverage
ValidationRule(...)-73.33%50%
ValidationRule(...)-73.33%50%
ValidationRule(...)-0%0%
ValidationRule(...)-0%0%
ValidationRule(...)-0%0%
ValidationRule(...)-0%0%
ValidationRule(...)-0%0%
ValidationRule(...)-66.67%50%
IsValid(...)-66.67%50%

File(s)

D:\a\1\s\src\ReactiveUI.Validation\Extensions\ValidatableViewModelExtensions.cs

#LineLine coverage
 1// Copyright (c) 2020 .NET Foundation and Contributors. All rights reserved.
 2// Licensed to the .NET Foundation under one or more agreements.
 3// The .NET Foundation licenses this file to you under the MIT license.
 4// See the LICENSE file in the project root for full license information.
 5
 6using System;
 7using System.Linq.Expressions;
 8using ReactiveUI.Validation.Abstractions;
 9using ReactiveUI.Validation.Components;
 10using ReactiveUI.Validation.Helpers;
 11
 12namespace ReactiveUI.Validation.Extensions
 13{
 14    /// <summary>
 15    /// Extensions methods associated to <see cref="IValidatableViewModel"/> instances.
 16    /// </summary>
 17    public static class ValidatableViewModelExtensions
 18    {
 19        /// <summary>
 20        /// Setup a validation rule for a specified ViewModel property with static error message.
 21        /// </summary>
 22        /// <typeparam name="TViewModel">ViewModel type.</typeparam>
 23        /// <typeparam name="TViewModelProp">ViewModel property type.</typeparam>
 24        /// <param name="viewModel">ViewModel instance.</param>
 25        /// <param name="viewModelProperty">ViewModel property.</param>
 26        /// <param name="isPropertyValid">Func to define if the viewModelProperty is valid or not.</param>
 27        /// <param name="message">Validation error message.</param>
 28        /// <returns>Returns a <see cref="ValidationHelper"/> object.</returns>
 29        public static ValidationHelper ValidationRule<TViewModel, TViewModelProp>(
 30            this TViewModel viewModel,
 31            Expression<Func<TViewModel, TViewModelProp>> viewModelProperty,
 32            Func<TViewModelProp, bool> isPropertyValid,
 33            string message)
 34            where TViewModel : ReactiveObject, IValidatableViewModel
 35        {
 2836            if (viewModel is null)
 37            {
 038                throw new ArgumentNullException(nameof(viewModel));
 39            }
 40
 2841            if (viewModelProperty is null)
 42            {
 043                throw new ArgumentNullException(nameof(viewModelProperty));
 44            }
 45
 2846            if (isPropertyValid is null)
 47            {
 048                throw new ArgumentNullException(nameof(isPropertyValid));
 49            }
 50
 2851            if (string.IsNullOrEmpty(message))
 52            {
 053                throw new ArgumentNullException(nameof(message));
 54            }
 55
 56            // We need to associate the ViewModel property
 57            // with something that can be easily looked up and bound to
 2858            var propValidation = new BasePropertyValidation<TViewModel, TViewModelProp>(
 2859                viewModel,
 2860                viewModelProperty,
 2861                isPropertyValid,
 2862                message);
 63
 2864            viewModel.ValidationContext.Add(propValidation);
 2865            return new ValidationHelper(propValidation);
 66        }
 67
 68        /// <summary>
 69        /// Setup a validation rule for a specified ViewModel property with dynamic error message.
 70        /// </summary>
 71        /// <typeparam name="TViewModel">ViewModel type.</typeparam>
 72        /// <typeparam name="TViewModelProp">ViewModel property type.</typeparam>
 73        /// <param name="viewModel">ViewModel instance.</param>
 74        /// <param name="viewModelProperty">ViewModel property.</param>
 75        /// <param name="isPropertyValid">Func to define if the viewModelProperty is valid or not.</param>
 76        /// <param name="message">Func to define the validation error message based on the viewModelProperty value.</par
 77        /// <returns>Returns a <see cref="ValidationHelper"/> object.</returns>
 78        public static ValidationHelper ValidationRule<TViewModel, TViewModelProp>(
 79            this TViewModel viewModel,
 80            Expression<Func<TViewModel, TViewModelProp>> viewModelProperty,
 81            Func<TViewModelProp, bool> isPropertyValid,
 82            Func<TViewModelProp, string> message)
 83            where TViewModel : ReactiveObject, IValidatableViewModel
 84        {
 485            if (viewModel is null)
 86            {
 087                throw new ArgumentNullException(nameof(viewModel));
 88            }
 89
 490            if (viewModelProperty is null)
 91            {
 092                throw new ArgumentNullException(nameof(viewModelProperty));
 93            }
 94
 495            if (isPropertyValid is null)
 96            {
 097                throw new ArgumentNullException(nameof(isPropertyValid));
 98            }
 99
 4100            if (message is null)
 101            {
 0102                throw new ArgumentNullException(nameof(message));
 103            }
 104
 105            // We need to associate the ViewModel property
 106            // with something that can be easily looked up and bound to
 4107            var propValidation = new BasePropertyValidation<TViewModel, TViewModelProp>(
 4108                viewModel,
 4109                viewModelProperty,
 4110                isPropertyValid,
 4111                message);
 112
 4113            viewModel.ValidationContext.Add(propValidation);
 4114            return new ValidationHelper(propValidation);
 115        }
 116
 117        /// <summary>
 118        /// Setup a validation rule with a general observable indicating validity.
 119        /// </summary>
 120        /// <typeparam name="TViewModel">ViewModel type.</typeparam>
 121        /// <param name="viewModel">ViewModel instance.</param>
 122        /// <param name="viewModelObservableProperty">Func to define if the viewModel is valid or not.</param>
 123        /// <param name="message">Validation error message.</param>
 124        /// <returns>Returns a <see cref="ValidationHelper"/> object.</returns>
 125        /// <remarks>
 126        /// It should be noted that the observable should provide an initial value, otherwise that can result
 127        /// in an inconsistent performance.
 128        /// </remarks>
 129        public static ValidationHelper ValidationRule<TViewModel>(
 130            this TViewModel viewModel,
 131            Func<TViewModel, IObservable<bool>> viewModelObservableProperty,
 132            string message)
 133            where TViewModel : ReactiveObject, IValidatableViewModel
 134        {
 0135            if (viewModel is null)
 136            {
 0137                throw new ArgumentNullException(nameof(viewModel));
 138            }
 139
 0140            if (viewModelObservableProperty is null)
 141            {
 0142                throw new ArgumentNullException(nameof(viewModelObservableProperty));
 143            }
 144
 0145            if (message is null)
 146            {
 0147                throw new ArgumentNullException(nameof(message));
 148            }
 149
 0150            var validation = new ModelObservableValidation<TViewModel>(
 0151                viewModel, viewModelObservableProperty, message);
 152
 0153            viewModel.ValidationContext.Add(validation);
 0154            return new ValidationHelper(validation);
 155        }
 156
 157        /// <summary>
 158        /// Setup a validation rule with a general observable indicating validity.
 159        /// </summary>
 160        /// <typeparam name="TViewModel">ViewModel type.</typeparam>
 161        /// <param name="viewModel">ViewModel instance.</param>
 162        /// <param name="viewModelObservableProperty">Func to define if the viewModel is valid or not.</param>
 163        /// <param name="messageFunc">Func to define the validation error message based on the viewModel and viewModelOb
 164        /// <returns>Returns a <see cref="ValidationHelper"/> object.</returns>
 165        /// <remarks>
 166        /// It should be noted that the observable should provide an initial value, otherwise that can result
 167        /// in an inconsistent performance.
 168        /// </remarks>
 169        public static ValidationHelper ValidationRule<TViewModel>(
 170            this TViewModel viewModel,
 171            Func<TViewModel, IObservable<bool>> viewModelObservableProperty,
 172            Func<TViewModel, string> messageFunc)
 173            where TViewModel : ReactiveObject, IValidatableViewModel
 174        {
 0175            if (viewModel is null)
 176            {
 0177                throw new ArgumentNullException(nameof(viewModel));
 178            }
 179
 0180            if (viewModelObservableProperty is null)
 181            {
 0182                throw new ArgumentNullException(nameof(viewModelObservableProperty));
 183            }
 184
 0185            if (messageFunc is null)
 186            {
 0187                throw new ArgumentNullException(nameof(messageFunc));
 188            }
 189
 0190            var validation = new ModelObservableValidation<TViewModel>(
 0191                viewModel, viewModelObservableProperty, messageFunc);
 192
 0193            viewModel.ValidationContext.Add(validation);
 0194            return new ValidationHelper(validation);
 195        }
 196
 197        /// <summary>
 198        /// Setup a validation rule with a general observable indicating validity.
 199        /// </summary>
 200        /// <typeparam name="TViewModel">ViewModel type.</typeparam>
 201        /// <param name="viewModel">ViewModel instance.</param>
 202        /// <param name="viewModelObservableProperty">Func to define if the viewModel is valid or not.</param>
 203        /// <param name="messageFunc">Func to define the validation error message based on the viewModel and viewModelOb
 204        /// <returns>Returns a <see cref="ValidationHelper"/> object.</returns>
 205        /// <remarks>
 206        /// It should be noted that the observable should provide an initial value, otherwise that can result
 207        /// in an inconsistent performance.
 208        /// </remarks>
 209        [Obsolete("This overload is planned for future removal. Consider using either the overload that accepts a " +
 210                  "Func<TViewModel, string> as the messageFunc parameter, or the overload that accepts a string.")]
 211        public static ValidationHelper ValidationRule<TViewModel>(
 212            this TViewModel viewModel,
 213            Func<TViewModel, IObservable<bool>> viewModelObservableProperty,
 214            Func<TViewModel, bool, string> messageFunc)
 215            where TViewModel : ReactiveObject, IValidatableViewModel
 216        {
 0217            if (viewModel is null)
 218            {
 0219                throw new ArgumentNullException(nameof(viewModel));
 220            }
 221
 0222            if (viewModelObservableProperty is null)
 223            {
 0224                throw new ArgumentNullException(nameof(viewModelObservableProperty));
 225            }
 226
 0227            if (messageFunc is null)
 228            {
 0229                throw new ArgumentNullException(nameof(messageFunc));
 230            }
 231
 0232            var validation = new ModelObservableValidation<TViewModel>(
 0233                viewModel, viewModelObservableProperty, messageFunc);
 234
 0235            viewModel.ValidationContext.Add(validation);
 0236            return new ValidationHelper(validation);
 237        }
 238
 239        /// <summary>
 240        /// Setup a validation rule with a general observable indicating validity.
 241        /// </summary>
 242        /// <typeparam name="TViewModel">ViewModel type.</typeparam>
 243        /// <typeparam name="TViewModelProp">ViewModel property type.</typeparam>
 244        /// <param name="viewModel">ViewModel instance.</param>
 245        /// <param name="viewModelProperty">ViewModel property referenced in viewModelObservableProperty.</param>
 246        /// <param name="viewModelObservableProperty">Func to define if the viewModel is valid or not.</param>
 247        /// <param name="message">Validation error message.</param>
 248        /// <returns>Returns a <see cref="ValidationHelper"/> object.</returns>
 249        /// <remarks>
 250        /// It should be noted that the observable should provide an initial value, otherwise that can result
 251        /// in an inconsistent performance.
 252        /// </remarks>
 253        public static ValidationHelper ValidationRule<TViewModel, TViewModelProp>(
 254            this TViewModel viewModel,
 255            Expression<Func<TViewModel, TViewModelProp>> viewModelProperty,
 256            Func<TViewModel, IObservable<bool>> viewModelObservableProperty,
 257            string message)
 258            where TViewModel : ReactiveObject, IValidatableViewModel
 259        {
 0260            if (viewModel is null)
 261            {
 0262                throw new ArgumentNullException(nameof(viewModel));
 263            }
 264
 0265            if (viewModelProperty is null)
 266            {
 0267                throw new ArgumentNullException(nameof(viewModelProperty));
 268            }
 269
 0270            if (viewModelObservableProperty is null)
 271            {
 0272                throw new ArgumentNullException(nameof(viewModelObservableProperty));
 273            }
 274
 0275            if (message is null)
 276            {
 0277                throw new ArgumentNullException(nameof(message));
 278            }
 279
 0280            var validation = new ModelObservableValidation<TViewModel, TViewModelProp>(
 0281                viewModel, viewModelProperty, viewModelObservableProperty, message);
 282
 0283            viewModel.ValidationContext.Add(validation);
 0284            return new ValidationHelper(validation);
 285        }
 286
 287        /// <summary>
 288        /// Setup a validation rule with a general observable indicating validity.
 289        /// </summary>
 290        /// <typeparam name="TViewModel">ViewModel type.</typeparam>
 291        /// <typeparam name="TViewModelProp">ViewModel property type.</typeparam>
 292        /// <param name="viewModel">ViewModel instance.</param>
 293        /// <param name="viewModelProperty">ViewModel property referenced in viewModelObservableProperty.</param>
 294        /// <param name="viewModelObservableProperty">Func to define if the viewModel is valid or not.</param>
 295        /// <param name="messageFunc">Func to define the validation error message based on the viewModel and viewModelOb
 296        /// <returns>Returns a <see cref="ValidationHelper"/> object.</returns>
 297        /// <remarks>
 298        /// It should be noted that the observable should provide an initial value, otherwise that can result
 299        /// in an inconsistent performance.
 300        /// </remarks>
 301        public static ValidationHelper ValidationRule<TViewModel, TViewModelProp>(
 302            this TViewModel viewModel,
 303            Expression<Func<TViewModel, TViewModelProp>> viewModelProperty,
 304            Func<TViewModel, IObservable<bool>> viewModelObservableProperty,
 305            Func<TViewModel, string> messageFunc)
 306            where TViewModel : ReactiveObject, IValidatableViewModel
 307        {
 0308            if (viewModel is null)
 309            {
 0310                throw new ArgumentNullException(nameof(viewModel));
 311            }
 312
 0313            if (viewModelProperty is null)
 314            {
 0315                throw new ArgumentNullException(nameof(viewModelProperty));
 316            }
 317
 0318            if (viewModelObservableProperty is null)
 319            {
 0320                throw new ArgumentNullException(nameof(viewModelObservableProperty));
 321            }
 322
 0323            if (messageFunc is null)
 324            {
 0325                throw new ArgumentNullException(nameof(messageFunc));
 326            }
 327
 0328            var validation = new ModelObservableValidation<TViewModel, TViewModelProp>(
 0329                viewModel, viewModelProperty, viewModelObservableProperty, messageFunc);
 330
 0331            viewModel.ValidationContext.Add(validation);
 0332            return new ValidationHelper(validation);
 333        }
 334
 335        /// <summary>
 336        /// Setup a validation rule with a general observable indicating validity.
 337        /// </summary>
 338        /// <typeparam name="TViewModel">ViewModel type.</typeparam>
 339        /// <typeparam name="TViewModelProp">ViewModel property type.</typeparam>
 340        /// <param name="viewModel">ViewModel instance.</param>
 341        /// <param name="viewModelProperty">ViewModel property referenced in viewModelObservableProperty.</param>
 342        /// <param name="viewModelObservableProperty">Func to define if the viewModel is valid or not.</param>
 343        /// <param name="messageFunc">Func to define the validation error message based on the viewModel and viewModelOb
 344        /// <returns>Returns a <see cref="ValidationHelper"/> object.</returns>
 345        /// <remarks>
 346        /// It should be noted that the observable should provide an initial value, otherwise that can result
 347        /// in an inconsistent performance.
 348        /// </remarks>
 349        [Obsolete("This overload is planned for future removal. Consider using either the overload that accepts a " +
 350                  "Func<TViewModel, string> as the messageFunc parameter, or the overload that accepts a string.")]
 351        public static ValidationHelper ValidationRule<TViewModel, TViewModelProp>(
 352            this TViewModel viewModel,
 353            Expression<Func<TViewModel, TViewModelProp>> viewModelProperty,
 354            Func<TViewModel, IObservable<bool>> viewModelObservableProperty,
 355            Func<TViewModel, bool, string> messageFunc)
 356            where TViewModel : ReactiveObject, IValidatableViewModel
 357        {
 4358            if (viewModel is null)
 359            {
 0360                throw new ArgumentNullException(nameof(viewModel));
 361            }
 362
 4363            if (viewModelProperty is null)
 364            {
 0365                throw new ArgumentNullException(nameof(viewModelProperty));
 366            }
 367
 4368            if (viewModelObservableProperty is null)
 369            {
 0370                throw new ArgumentNullException(nameof(viewModelObservableProperty));
 371            }
 372
 4373            if (messageFunc is null)
 374            {
 0375                throw new ArgumentNullException(nameof(messageFunc));
 376            }
 377
 4378            var validation = new ModelObservableValidation<TViewModel, TViewModelProp>(
 4379                viewModel, viewModelProperty, viewModelObservableProperty, messageFunc);
 380
 4381            viewModel.ValidationContext.Add(validation);
 4382            return new ValidationHelper(validation);
 383        }
 384
 385        /// <summary>
 386        /// Gets an observable for the validity of the ViewModel.
 387        /// </summary>
 388        /// <typeparam name="TViewModel">ViewModel type.</typeparam>
 389        /// <param name="viewModel">ViewModel instance.</param>
 390        /// <returns>Returns true if the ValidationContext is valid, otherwise false.</returns>
 391        public static IObservable<bool> IsValid<TViewModel>(this TViewModel viewModel)
 392            where TViewModel : ReactiveObject, IValidatableViewModel
 393        {
 2394            if (viewModel == null)
 395            {
 0396                throw new ArgumentNullException(nameof(viewModel));
 397            }
 398
 2399            return viewModel.ValidationContext.Valid;
 400        }
 401    }
 402}