< Summary

Class:ReactiveUI.Validation.TemplateGenerators.BasePropertyValidation`7
Assembly:ReactiveUI.Validation
File(s):D:\a\1\s\src\ReactiveUI.Validation\TemplateGenerators\PropertyValidationGenerator.cs
Covered lines:0
Uncovered lines:56
Coverable lines:56
Total lines:803
Line coverage:0% (0 of 56)
Covered branches:0
Total branches:24
Branch coverage:0% (0 of 24)

Metrics

MethodCyclomatic complexity Line coverage Branch coverage
.ctor(...)-0%0%
.ctor(...)-0%0%
.ctor(...)-0%100%
get_LastValue()-0%100%
GetValidationChangeObservable()-0%100%
Dispose(...)-0%0%
GetMessage(...)-0%100%
Activate()-0%0%

File(s)

D:\a\1\s\src\ReactiveUI.Validation\TemplateGenerators\PropertyValidationGenerator.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
 6//------------------------------------------------------------------------------
 7// <auto-generated>
 8//    This code was generated from a template.
 9//
 10//    Manual changes to this file may cause unexpected behavior in your application.
 11//    Manual changes to this file will be overwritten if the code is regenerated.
 12// </auto-generated>
 13//------------------------------------------------------------------------------
 14
 15using System;
 16using System.Diagnostics.CodeAnalysis;
 17using System.Linq.Expressions;
 18using System.Reactive.Disposables;
 19using System.Reactive.Linq;
 20using System.Reactive.Subjects;
 21using ReactiveUI.Validation.Collections;
 22using ReactiveUI.Validation.Comparators;
 23using ReactiveUI.Validation.Components;
 24using ReactiveUI.Validation.States;
 25
 26namespace ReactiveUI.Validation.TemplateGenerators
 27{
 28
 29    /// <inheritdoc />
 30    [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1649:FileHeaderFileNameDocumentationMustMatchTypeName", Ju
 31    [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Sa
 32    public sealed class BasePropertyValidation<TViewModel, TProperty1, TProperty2>
 33        : BasePropertyValidation<TViewModel>
 34    {
 35        /// <summary>
 36        /// Represents the current value.
 37        /// </summary>
 38        private readonly Subject<(TProperty1, TProperty2)> _valueSubject = new Subject<(TProperty1, TProperty2)>();
 39
 40        /// <summary>
 41        /// The validation message factory.
 42        /// </summary>
 43        private readonly Func<(TProperty1, TProperty2), bool, ValidationText> _message;
 44
 45        /// <summary>
 46        /// The connected observable to see updates in properties being validated.
 47        /// </summary>
 48        private readonly IConnectableObservable<(TProperty1, TProperty2)> _valueConnectedObservable;
 49
 50        /// <summary>
 51        /// Function to determine if valid or not.
 52        /// </summary>
 53        private readonly Func<(TProperty1, TProperty2), bool> _isValidFunc;
 54
 55        private CompositeDisposable _disposables = new CompositeDisposable();
 56
 57        /// <summary>
 58        /// Are we connected.
 59        /// </summary>
 60        private bool _connected;
 61
 62        [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented", Justification = "Gener
 63        public BasePropertyValidation(
 64            TViewModel viewModel,
 65            Expression<Func<TViewModel, TProperty1>> property1,
 66            Expression<Func<TViewModel, TProperty2>> property2,
 67            Func<(TProperty1, TProperty2), bool> isValidFunc,
 68            Func<(TProperty1, TProperty2), string> message)
 69            : this(viewModel, property1, property2, isValidFunc, (p, v) => new ValidationText(v ? string.Empty : message
 70        {
 71        }
 72
 73        [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented", Justification = "Gener
 74        public BasePropertyValidation(
 75            TViewModel viewModel,
 76            Expression<Func<TViewModel, TProperty1>> property1,
 77            Expression<Func<TViewModel, TProperty2>> property2,
 78            Func<(TProperty1, TProperty2), bool> isValidFunc,
 79            Func<(TProperty1, TProperty2), bool, string> messageFunc)
 80            : this(viewModel, property1, property2, isValidFunc, (p, v) => new ValidationText(messageFunc(p, v)))
 81        {
 82        }
 83
 84        [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented", Justification = "Gener
 85        public BasePropertyValidation(
 86            TViewModel viewModel,
 87            Expression<Func<TViewModel, TProperty1>> property1,
 88            Expression<Func<TViewModel, TProperty2>> property2,
 89            Func<(TProperty1, TProperty2), bool> isValidFunc,
 90            Func<(TProperty1, TProperty2), bool, ValidationText> message)
 91        {
 92            if (property1 is null)
 93            {
 94                throw new ArgumentNullException(nameof(property1));
 95            }
 96
 97            if (property2 is null)
 98            {
 99                throw new ArgumentNullException(nameof(property2));
 100            }
 101
 102            _message = message ?? throw new ArgumentNullException(nameof(message));
 103            _isValidFunc = isValidFunc ?? throw new ArgumentNullException(nameof(isValidFunc));
 104
 105            // Add the properties used to our list
 106            AddProperty(property1);
 107            AddProperty(property2);
 108            _disposables.Add(_valueSubject.Subscribe(v => LastValue = v));
 109
 110            // Setup a connected observable to see when values change and cast that to our value subject
 111            _valueConnectedObservable = viewModel.WhenAnyValue(property1, property2)
 112                .DistinctUntilChanged()
 113                .Multicast(_valueSubject);
 114        }
 115
 116        /// <summary>
 117        /// Gets or sets the last calculated value of the properties.
 118        /// </summary>
 119        private (TProperty1, TProperty2) LastValue { get; set; }
 120
 121        /// <inheritdoc/>
 122        protected override IObservable<ValidationState> GetValidationChangeObservable()
 123        {
 124            Activate();
 125
 126            return _valueSubject.Select(value =>
 127            {
 128                var isValid = _isValidFunc(value);
 129                return new ValidationState(isValid, GetMessage(value, isValid), this);
 130            }).DistinctUntilChanged(new ValidationStateComparer());
 131        }
 132
 133        /// <inheritdoc/>
 134        protected override void Dispose(bool disposing)
 135        {
 136            if (disposing)
 137            {
 138                _disposables?.Dispose();
 139            }
 140        }
 141
 142        /// <summary>
 143        /// Gets the validation message.
 144        /// </summary>
 145        /// <param name="params">ViewModel properties.</param>
 146        /// <param name="isValid">Whether the property is valid or not.</param>
 147        /// <returns>Returns the <see cref="ValidationText"/> object.</returns>
 148        private ValidationText GetMessage((TProperty1, TProperty2) @params, bool isValid)
 149        {
 150            return _message(@params, isValid);
 151        }
 152
 153        /// <summary>
 154        /// Activate the connection to ensure we start seeing validations.
 155        /// </summary>
 156        private void Activate()
 157        {
 158            if (!_connected)
 159            {
 160                _connected = true;
 161                _disposables.Add(_valueConnectedObservable.Connect());
 162            }
 163        }
 164    }
 165
 166    /// <inheritdoc />
 167    [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1649:FileHeaderFileNameDocumentationMustMatchTypeName", Ju
 168    [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Sa
 169    public sealed class BasePropertyValidation<TViewModel, TProperty1, TProperty2, TProperty3>
 170        : BasePropertyValidation<TViewModel>
 171    {
 172        /// <summary>
 173        /// Represents the current value.
 174        /// </summary>
 175        private readonly Subject<(TProperty1, TProperty2, TProperty3)> _valueSubject = new Subject<(TProperty1, TPropert
 176
 177        /// <summary>
 178        /// The validation message factory.
 179        /// </summary>
 180        private readonly Func<(TProperty1, TProperty2, TProperty3), bool, ValidationText> _message;
 181
 182        /// <summary>
 183        /// The connected observable to see updates in properties being validated.
 184        /// </summary>
 185        private readonly IConnectableObservable<(TProperty1, TProperty2, TProperty3)> _valueConnectedObservable;
 186
 187        /// <summary>
 188        /// Function to determine if valid or not.
 189        /// </summary>
 190        private readonly Func<(TProperty1, TProperty2, TProperty3), bool> _isValidFunc;
 191
 192        private CompositeDisposable _disposables = new CompositeDisposable();
 193
 194        /// <summary>
 195        /// Are we connected.
 196        /// </summary>
 197        private bool _connected;
 198
 199        [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented", Justification = "Gener
 200        public BasePropertyValidation(
 201            TViewModel viewModel,
 202            Expression<Func<TViewModel, TProperty1>> property1,
 203            Expression<Func<TViewModel, TProperty2>> property2,
 204            Expression<Func<TViewModel, TProperty3>> property3,
 205            Func<(TProperty1, TProperty2, TProperty3), bool> isValidFunc,
 206            Func<(TProperty1, TProperty2, TProperty3), string> message)
 207            : this(viewModel, property1, property2, property3, isValidFunc, (p, v) => new ValidationText(v ? string.Empt
 208        {
 209        }
 210
 211        [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented", Justification = "Gener
 212        public BasePropertyValidation(
 213            TViewModel viewModel,
 214            Expression<Func<TViewModel, TProperty1>> property1,
 215            Expression<Func<TViewModel, TProperty2>> property2,
 216            Expression<Func<TViewModel, TProperty3>> property3,
 217            Func<(TProperty1, TProperty2, TProperty3), bool> isValidFunc,
 218            Func<(TProperty1, TProperty2, TProperty3), bool, string> messageFunc)
 219            : this(viewModel, property1, property2, property3, isValidFunc, (p, v) => new ValidationText(messageFunc(p, 
 220        {
 221        }
 222
 223        [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented", Justification = "Gener
 224        public BasePropertyValidation(
 225            TViewModel viewModel,
 226            Expression<Func<TViewModel, TProperty1>> property1,
 227            Expression<Func<TViewModel, TProperty2>> property2,
 228            Expression<Func<TViewModel, TProperty3>> property3,
 229            Func<(TProperty1, TProperty2, TProperty3), bool> isValidFunc,
 230            Func<(TProperty1, TProperty2, TProperty3), bool, ValidationText> message)
 231        {
 232            if (property1 is null)
 233            {
 234                throw new ArgumentNullException(nameof(property1));
 235            }
 236
 237            if (property2 is null)
 238            {
 239                throw new ArgumentNullException(nameof(property2));
 240            }
 241
 242            if (property3 is null)
 243            {
 244                throw new ArgumentNullException(nameof(property3));
 245            }
 246
 247            _message = message ?? throw new ArgumentNullException(nameof(message));
 248            _isValidFunc = isValidFunc ?? throw new ArgumentNullException(nameof(isValidFunc));
 249
 250            // Add the properties used to our list
 251            AddProperty(property1);
 252            AddProperty(property2);
 253            AddProperty(property3);
 254            _disposables.Add(_valueSubject.Subscribe(v => LastValue = v));
 255
 256            // Setup a connected observable to see when values change and cast that to our value subject
 257            _valueConnectedObservable = viewModel.WhenAnyValue(property1, property2, property3)
 258                .DistinctUntilChanged()
 259                .Multicast(_valueSubject);
 260        }
 261
 262        /// <summary>
 263        /// Gets or sets the last calculated value of the properties.
 264        /// </summary>
 265        private (TProperty1, TProperty2, TProperty3) LastValue { get; set; }
 266
 267        /// <inheritdoc/>
 268        protected override IObservable<ValidationState> GetValidationChangeObservable()
 269        {
 270            Activate();
 271
 272            return _valueSubject.Select(value =>
 273            {
 274                var isValid = _isValidFunc(value);
 275                return new ValidationState(isValid, GetMessage(value, isValid), this);
 276            }).DistinctUntilChanged(new ValidationStateComparer());
 277        }
 278
 279        /// <inheritdoc/>
 280        protected override void Dispose(bool disposing)
 281        {
 282            if (disposing)
 283            {
 284                _disposables?.Dispose();
 285            }
 286        }
 287
 288        /// <summary>
 289        /// Gets the validation message.
 290        /// </summary>
 291        /// <param name="params">ViewModel properties.</param>
 292        /// <param name="isValid">Whether the property is valid or not.</param>
 293        /// <returns>Returns the <see cref="ValidationText"/> object.</returns>
 294        private ValidationText GetMessage((TProperty1, TProperty2, TProperty3) @params, bool isValid)
 295        {
 296            return _message(@params, isValid);
 297        }
 298
 299        /// <summary>
 300        /// Activate the connection to ensure we start seeing validations.
 301        /// </summary>
 302        private void Activate()
 303        {
 304            if (!_connected)
 305            {
 306                _connected = true;
 307                _disposables.Add(_valueConnectedObservable.Connect());
 308            }
 309        }
 310    }
 311
 312    /// <inheritdoc />
 313    [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1649:FileHeaderFileNameDocumentationMustMatchTypeName", Ju
 314    [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Sa
 315    public sealed class BasePropertyValidation<TViewModel, TProperty1, TProperty2, TProperty3, TProperty4>
 316        : BasePropertyValidation<TViewModel>
 317    {
 318        /// <summary>
 319        /// Represents the current value.
 320        /// </summary>
 321        private readonly Subject<(TProperty1, TProperty2, TProperty3, TProperty4)> _valueSubject = new Subject<(TPropert
 322
 323        /// <summary>
 324        /// The validation message factory.
 325        /// </summary>
 326        private readonly Func<(TProperty1, TProperty2, TProperty3, TProperty4), bool, ValidationText> _message;
 327
 328        /// <summary>
 329        /// The connected observable to see updates in properties being validated.
 330        /// </summary>
 331        private readonly IConnectableObservable<(TProperty1, TProperty2, TProperty3, TProperty4)> _valueConnectedObserva
 332
 333        /// <summary>
 334        /// Function to determine if valid or not.
 335        /// </summary>
 336        private readonly Func<(TProperty1, TProperty2, TProperty3, TProperty4), bool> _isValidFunc;
 337
 338        private CompositeDisposable _disposables = new CompositeDisposable();
 339
 340        /// <summary>
 341        /// Are we connected.
 342        /// </summary>
 343        private bool _connected;
 344
 345        [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented", Justification = "Gener
 346        public BasePropertyValidation(
 347            TViewModel viewModel,
 348            Expression<Func<TViewModel, TProperty1>> property1,
 349            Expression<Func<TViewModel, TProperty2>> property2,
 350            Expression<Func<TViewModel, TProperty3>> property3,
 351            Expression<Func<TViewModel, TProperty4>> property4,
 352            Func<(TProperty1, TProperty2, TProperty3, TProperty4), bool> isValidFunc,
 353            Func<(TProperty1, TProperty2, TProperty3, TProperty4), string> message)
 354            : this(viewModel, property1, property2, property3, property4, isValidFunc, (p, v) => new ValidationText(v ? 
 355        {
 356        }
 357
 358        [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented", Justification = "Gener
 359        public BasePropertyValidation(
 360            TViewModel viewModel,
 361            Expression<Func<TViewModel, TProperty1>> property1,
 362            Expression<Func<TViewModel, TProperty2>> property2,
 363            Expression<Func<TViewModel, TProperty3>> property3,
 364            Expression<Func<TViewModel, TProperty4>> property4,
 365            Func<(TProperty1, TProperty2, TProperty3, TProperty4), bool> isValidFunc,
 366            Func<(TProperty1, TProperty2, TProperty3, TProperty4), bool, string> messageFunc)
 367            : this(viewModel, property1, property2, property3, property4, isValidFunc, (p, v) => new ValidationText(mess
 368        {
 369        }
 370
 371        [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented", Justification = "Gener
 372        public BasePropertyValidation(
 373            TViewModel viewModel,
 374            Expression<Func<TViewModel, TProperty1>> property1,
 375            Expression<Func<TViewModel, TProperty2>> property2,
 376            Expression<Func<TViewModel, TProperty3>> property3,
 377            Expression<Func<TViewModel, TProperty4>> property4,
 378            Func<(TProperty1, TProperty2, TProperty3, TProperty4), bool> isValidFunc,
 379            Func<(TProperty1, TProperty2, TProperty3, TProperty4), bool, ValidationText> message)
 380        {
 381            if (property1 is null)
 382            {
 383                throw new ArgumentNullException(nameof(property1));
 384            }
 385
 386            if (property2 is null)
 387            {
 388                throw new ArgumentNullException(nameof(property2));
 389            }
 390
 391            if (property3 is null)
 392            {
 393                throw new ArgumentNullException(nameof(property3));
 394            }
 395
 396            if (property4 is null)
 397            {
 398                throw new ArgumentNullException(nameof(property4));
 399            }
 400
 401            _message = message ?? throw new ArgumentNullException(nameof(message));
 402            _isValidFunc = isValidFunc ?? throw new ArgumentNullException(nameof(isValidFunc));
 403
 404            // Add the properties used to our list
 405            AddProperty(property1);
 406            AddProperty(property2);
 407            AddProperty(property3);
 408            AddProperty(property4);
 409            _disposables.Add(_valueSubject.Subscribe(v => LastValue = v));
 410
 411            // Setup a connected observable to see when values change and cast that to our value subject
 412            _valueConnectedObservable = viewModel.WhenAnyValue(property1, property2, property3, property4)
 413                .DistinctUntilChanged()
 414                .Multicast(_valueSubject);
 415        }
 416
 417        /// <summary>
 418        /// Gets or sets the last calculated value of the properties.
 419        /// </summary>
 420        private (TProperty1, TProperty2, TProperty3, TProperty4) LastValue { get; set; }
 421
 422        /// <inheritdoc/>
 423        protected override IObservable<ValidationState> GetValidationChangeObservable()
 424        {
 425            Activate();
 426
 427            return _valueSubject.Select(value =>
 428            {
 429                var isValid = _isValidFunc(value);
 430                return new ValidationState(isValid, GetMessage(value, isValid), this);
 431            }).DistinctUntilChanged(new ValidationStateComparer());
 432        }
 433
 434        /// <inheritdoc/>
 435        protected override void Dispose(bool disposing)
 436        {
 437            if (disposing)
 438            {
 439                _disposables?.Dispose();
 440            }
 441        }
 442
 443        /// <summary>
 444        /// Gets the validation message.
 445        /// </summary>
 446        /// <param name="params">ViewModel properties.</param>
 447        /// <param name="isValid">Whether the property is valid or not.</param>
 448        /// <returns>Returns the <see cref="ValidationText"/> object.</returns>
 449        private ValidationText GetMessage((TProperty1, TProperty2, TProperty3, TProperty4) @params, bool isValid)
 450        {
 451            return _message(@params, isValid);
 452        }
 453
 454        /// <summary>
 455        /// Activate the connection to ensure we start seeing validations.
 456        /// </summary>
 457        private void Activate()
 458        {
 459            if (!_connected)
 460            {
 461                _connected = true;
 462                _disposables.Add(_valueConnectedObservable.Connect());
 463            }
 464        }
 465    }
 466
 467    /// <inheritdoc />
 468    [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1649:FileHeaderFileNameDocumentationMustMatchTypeName", Ju
 469    [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Sa
 470    public sealed class BasePropertyValidation<TViewModel, TProperty1, TProperty2, TProperty3, TProperty4, TProperty5>
 471        : BasePropertyValidation<TViewModel>
 472    {
 473        /// <summary>
 474        /// Represents the current value.
 475        /// </summary>
 476        private readonly Subject<(TProperty1, TProperty2, TProperty3, TProperty4, TProperty5)> _valueSubject = new Subje
 477
 478        /// <summary>
 479        /// The validation message factory.
 480        /// </summary>
 481        private readonly Func<(TProperty1, TProperty2, TProperty3, TProperty4, TProperty5), bool, ValidationText> _messa
 482
 483        /// <summary>
 484        /// The connected observable to see updates in properties being validated.
 485        /// </summary>
 486        private readonly IConnectableObservable<(TProperty1, TProperty2, TProperty3, TProperty4, TProperty5)> _valueConn
 487
 488        /// <summary>
 489        /// Function to determine if valid or not.
 490        /// </summary>
 491        private readonly Func<(TProperty1, TProperty2, TProperty3, TProperty4, TProperty5), bool> _isValidFunc;
 492
 493        private CompositeDisposable _disposables = new CompositeDisposable();
 494
 495        /// <summary>
 496        /// Are we connected.
 497        /// </summary>
 498        private bool _connected;
 499
 500        [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented", Justification = "Gener
 501        public BasePropertyValidation(
 502            TViewModel viewModel,
 503            Expression<Func<TViewModel, TProperty1>> property1,
 504            Expression<Func<TViewModel, TProperty2>> property2,
 505            Expression<Func<TViewModel, TProperty3>> property3,
 506            Expression<Func<TViewModel, TProperty4>> property4,
 507            Expression<Func<TViewModel, TProperty5>> property5,
 508            Func<(TProperty1, TProperty2, TProperty3, TProperty4, TProperty5), bool> isValidFunc,
 509            Func<(TProperty1, TProperty2, TProperty3, TProperty4, TProperty5), string> message)
 510            : this(viewModel, property1, property2, property3, property4, property5, isValidFunc, (p, v) => new Validati
 511        {
 512        }
 513
 514        [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented", Justification = "Gener
 515        public BasePropertyValidation(
 516            TViewModel viewModel,
 517            Expression<Func<TViewModel, TProperty1>> property1,
 518            Expression<Func<TViewModel, TProperty2>> property2,
 519            Expression<Func<TViewModel, TProperty3>> property3,
 520            Expression<Func<TViewModel, TProperty4>> property4,
 521            Expression<Func<TViewModel, TProperty5>> property5,
 522            Func<(TProperty1, TProperty2, TProperty3, TProperty4, TProperty5), bool> isValidFunc,
 523            Func<(TProperty1, TProperty2, TProperty3, TProperty4, TProperty5), bool, string> messageFunc)
 524            : this(viewModel, property1, property2, property3, property4, property5, isValidFunc, (p, v) => new Validati
 525        {
 526        }
 527
 528        [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented", Justification = "Gener
 529        public BasePropertyValidation(
 530            TViewModel viewModel,
 531            Expression<Func<TViewModel, TProperty1>> property1,
 532            Expression<Func<TViewModel, TProperty2>> property2,
 533            Expression<Func<TViewModel, TProperty3>> property3,
 534            Expression<Func<TViewModel, TProperty4>> property4,
 535            Expression<Func<TViewModel, TProperty5>> property5,
 536            Func<(TProperty1, TProperty2, TProperty3, TProperty4, TProperty5), bool> isValidFunc,
 537            Func<(TProperty1, TProperty2, TProperty3, TProperty4, TProperty5), bool, ValidationText> message)
 538        {
 539            if (property1 is null)
 540            {
 541                throw new ArgumentNullException(nameof(property1));
 542            }
 543
 544            if (property2 is null)
 545            {
 546                throw new ArgumentNullException(nameof(property2));
 547            }
 548
 549            if (property3 is null)
 550            {
 551                throw new ArgumentNullException(nameof(property3));
 552            }
 553
 554            if (property4 is null)
 555            {
 556                throw new ArgumentNullException(nameof(property4));
 557            }
 558
 559            if (property5 is null)
 560            {
 561                throw new ArgumentNullException(nameof(property5));
 562            }
 563
 564            _message = message ?? throw new ArgumentNullException(nameof(message));
 565            _isValidFunc = isValidFunc ?? throw new ArgumentNullException(nameof(isValidFunc));
 566
 567            // Add the properties used to our list
 568            AddProperty(property1);
 569            AddProperty(property2);
 570            AddProperty(property3);
 571            AddProperty(property4);
 572            AddProperty(property5);
 573            _disposables.Add(_valueSubject.Subscribe(v => LastValue = v));
 574
 575            // Setup a connected observable to see when values change and cast that to our value subject
 576            _valueConnectedObservable = viewModel.WhenAnyValue(property1, property2, property3, property4, property5)
 577                .DistinctUntilChanged()
 578                .Multicast(_valueSubject);
 579        }
 580
 581        /// <summary>
 582        /// Gets or sets the last calculated value of the properties.
 583        /// </summary>
 584        private (TProperty1, TProperty2, TProperty3, TProperty4, TProperty5) LastValue { get; set; }
 585
 586        /// <inheritdoc/>
 587        protected override IObservable<ValidationState> GetValidationChangeObservable()
 588        {
 589            Activate();
 590
 591            return _valueSubject.Select(value =>
 592            {
 593                var isValid = _isValidFunc(value);
 594                return new ValidationState(isValid, GetMessage(value, isValid), this);
 595            }).DistinctUntilChanged(new ValidationStateComparer());
 596        }
 597
 598        /// <inheritdoc/>
 599        protected override void Dispose(bool disposing)
 600        {
 601            if (disposing)
 602            {
 603                _disposables?.Dispose();
 604            }
 605        }
 606
 607        /// <summary>
 608        /// Gets the validation message.
 609        /// </summary>
 610        /// <param name="params">ViewModel properties.</param>
 611        /// <param name="isValid">Whether the property is valid or not.</param>
 612        /// <returns>Returns the <see cref="ValidationText"/> object.</returns>
 613        private ValidationText GetMessage((TProperty1, TProperty2, TProperty3, TProperty4, TProperty5) @params, bool isV
 614        {
 615            return _message(@params, isValid);
 616        }
 617
 618        /// <summary>
 619        /// Activate the connection to ensure we start seeing validations.
 620        /// </summary>
 621        private void Activate()
 622        {
 623            if (!_connected)
 624            {
 625                _connected = true;
 626                _disposables.Add(_valueConnectedObservable.Connect());
 627            }
 628        }
 629    }
 630
 631    /// <inheritdoc />
 632    [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1649:FileHeaderFileNameDocumentationMustMatchTypeName", Ju
 633    [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Sa
 634    public sealed class BasePropertyValidation<TViewModel, TProperty1, TProperty2, TProperty3, TProperty4, TProperty5, T
 635        : BasePropertyValidation<TViewModel>
 636    {
 637        /// <summary>
 638        /// Represents the current value.
 639        /// </summary>
 0640        private readonly Subject<(TProperty1, TProperty2, TProperty3, TProperty4, TProperty5, TProperty6)> _valueSubject
 641
 642        /// <summary>
 643        /// The validation message factory.
 644        /// </summary>
 645        private readonly Func<(TProperty1, TProperty2, TProperty3, TProperty4, TProperty5, TProperty6), bool, Validation
 646
 647        /// <summary>
 648        /// The connected observable to see updates in properties being validated.
 649        /// </summary>
 650        private readonly IConnectableObservable<(TProperty1, TProperty2, TProperty3, TProperty4, TProperty5, TProperty6)
 651
 652        /// <summary>
 653        /// Function to determine if valid or not.
 654        /// </summary>
 655        private readonly Func<(TProperty1, TProperty2, TProperty3, TProperty4, TProperty5, TProperty6), bool> _isValidFu
 656
 0657        private CompositeDisposable _disposables = new CompositeDisposable();
 658
 659        /// <summary>
 660        /// Are we connected.
 661        /// </summary>
 662        private bool _connected;
 663
 664        [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented", Justification = "Gener
 665        public BasePropertyValidation(
 666            TViewModel viewModel,
 667            Expression<Func<TViewModel, TProperty1>> property1,
 668            Expression<Func<TViewModel, TProperty2>> property2,
 669            Expression<Func<TViewModel, TProperty3>> property3,
 670            Expression<Func<TViewModel, TProperty4>> property4,
 671            Expression<Func<TViewModel, TProperty5>> property5,
 672            Expression<Func<TViewModel, TProperty6>> property6,
 673            Func<(TProperty1, TProperty2, TProperty3, TProperty4, TProperty5, TProperty6), bool> isValidFunc,
 674            Func<(TProperty1, TProperty2, TProperty3, TProperty4, TProperty5, TProperty6), string> message)
 0675            : this(viewModel, property1, property2, property3, property4, property5, property6, isValidFunc, (p, v) => n
 676        {
 0677        }
 678
 679        [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented", Justification = "Gener
 680        public BasePropertyValidation(
 681            TViewModel viewModel,
 682            Expression<Func<TViewModel, TProperty1>> property1,
 683            Expression<Func<TViewModel, TProperty2>> property2,
 684            Expression<Func<TViewModel, TProperty3>> property3,
 685            Expression<Func<TViewModel, TProperty4>> property4,
 686            Expression<Func<TViewModel, TProperty5>> property5,
 687            Expression<Func<TViewModel, TProperty6>> property6,
 688            Func<(TProperty1, TProperty2, TProperty3, TProperty4, TProperty5, TProperty6), bool> isValidFunc,
 689            Func<(TProperty1, TProperty2, TProperty3, TProperty4, TProperty5, TProperty6), bool, string> messageFunc)
 0690            : this(viewModel, property1, property2, property3, property4, property5, property6, isValidFunc, (p, v) => n
 691        {
 0692        }
 693
 694        [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented", Justification = "Gener
 0695        public BasePropertyValidation(
 0696            TViewModel viewModel,
 0697            Expression<Func<TViewModel, TProperty1>> property1,
 0698            Expression<Func<TViewModel, TProperty2>> property2,
 0699            Expression<Func<TViewModel, TProperty3>> property3,
 0700            Expression<Func<TViewModel, TProperty4>> property4,
 0701            Expression<Func<TViewModel, TProperty5>> property5,
 0702            Expression<Func<TViewModel, TProperty6>> property6,
 0703            Func<(TProperty1, TProperty2, TProperty3, TProperty4, TProperty5, TProperty6), bool> isValidFunc,
 0704            Func<(TProperty1, TProperty2, TProperty3, TProperty4, TProperty5, TProperty6), bool, ValidationText> message
 705        {
 0706            if (property1 is null)
 707            {
 0708                throw new ArgumentNullException(nameof(property1));
 709            }
 710
 0711            if (property2 is null)
 712            {
 0713                throw new ArgumentNullException(nameof(property2));
 714            }
 715
 0716            if (property3 is null)
 717            {
 0718                throw new ArgumentNullException(nameof(property3));
 719            }
 720
 0721            if (property4 is null)
 722            {
 0723                throw new ArgumentNullException(nameof(property4));
 724            }
 725
 0726            if (property5 is null)
 727            {
 0728                throw new ArgumentNullException(nameof(property5));
 729            }
 730
 0731            if (property6 is null)
 732            {
 0733                throw new ArgumentNullException(nameof(property6));
 734            }
 735
 0736            _message = message ?? throw new ArgumentNullException(nameof(message));
 0737            _isValidFunc = isValidFunc ?? throw new ArgumentNullException(nameof(isValidFunc));
 738
 739            // Add the properties used to our list
 0740            AddProperty(property1);
 0741            AddProperty(property2);
 0742            AddProperty(property3);
 0743            AddProperty(property4);
 0744            AddProperty(property5);
 0745            AddProperty(property6);
 0746            _disposables.Add(_valueSubject.Subscribe(v => LastValue = v));
 747
 748            // Setup a connected observable to see when values change and cast that to our value subject
 0749            _valueConnectedObservable = viewModel.WhenAnyValue(property1, property2, property3, property4, property5, pr
 0750                .DistinctUntilChanged()
 0751                .Multicast(_valueSubject);
 0752        }
 753
 754        /// <summary>
 755        /// Gets or sets the last calculated value of the properties.
 756        /// </summary>
 0757        private (TProperty1, TProperty2, TProperty3, TProperty4, TProperty5, TProperty6) LastValue { get; set; }
 758
 759        /// <inheritdoc/>
 760        protected override IObservable<ValidationState> GetValidationChangeObservable()
 761        {
 0762            Activate();
 763
 0764            return _valueSubject.Select(value =>
 0765            {
 0766                var isValid = _isValidFunc(value);
 0767                return new ValidationState(isValid, GetMessage(value, isValid), this);
 0768            }).DistinctUntilChanged(new ValidationStateComparer());
 769        }
 770
 771        /// <inheritdoc/>
 772        protected override void Dispose(bool disposing)
 773        {
 0774            if (disposing)
 775            {
 0776                _disposables?.Dispose();
 777            }
 0778        }
 779
 780        /// <summary>
 781        /// Gets the validation message.
 782        /// </summary>
 783        /// <param name="params">ViewModel properties.</param>
 784        /// <param name="isValid">Whether the property is valid or not.</param>
 785        /// <returns>Returns the <see cref="ValidationText"/> object.</returns>
 786        private ValidationText GetMessage((TProperty1, TProperty2, TProperty3, TProperty4, TProperty5, TProperty6) @para
 787        {
 0788            return _message(@params, isValid);
 789        }
 790
 791        /// <summary>
 792        /// Activate the connection to ensure we start seeing validations.
 793        /// </summary>
 794        private void Activate()
 795        {
 0796            if (!_connected)
 797            {
 0798                _connected = true;
 0799                _disposables.Add(_valueConnectedObservable.Connect());
 800            }
 0801        }
 802    }
 803}