[release/v7.4.16] Fix Out-GridView by replacing use of obsolete BinaryFormatter with custom implementation (#27426)

This commit is contained in:
Aditya Patwardhan
2026-05-15 09:53:18 -07:00
committed by GitHub
parent 9495622835
commit 4f6d7cae62
27 changed files with 346 additions and 48 deletions
@@ -16,6 +16,23 @@ namespace Microsoft.Management.UI.Internal
[Serializable]
public abstract class ComparableValueFilterRule<T> : FilterRule where T : IComparable
{
/// <summary>
/// Initializes a new instance of the <see cref="ComparableValueFilterRule{T}"/> class.
/// </summary>
protected ComparableValueFilterRule()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ComparableValueFilterRule{T}"/> class.
/// </summary>
/// <param name="source">The source to initialize from.</param>
protected ComparableValueFilterRule(ComparableValueFilterRule<T> source)
: base(source)
{
this.DefaultNullValueEvaluation = source.DefaultNullValueEvaluation;
}
#region Properties
/// <summary>
@@ -17,7 +17,7 @@ namespace Microsoft.Management.UI.Internal
public class DoesNotEqualFilterRule<T> : EqualsFilterRule<T> where T : IComparable
{
/// <summary>
/// Initializes a new instance of the DoesNotEqualFilterRule class.
/// Initializes a new instance of the <see cref="DoesNotEqualFilterRule{T}"/> class.
/// </summary>
public DoesNotEqualFilterRule()
{
@@ -25,6 +25,15 @@ namespace Microsoft.Management.UI.Internal
this.DefaultNullValueEvaluation = true;
}
/// <summary>
/// Initializes a new instance of the <see cref="DoesNotEqualFilterRule{T}"/> class.
/// </summary>
/// <param name="source">The source to initialize from.</param>
public DoesNotEqualFilterRule(DoesNotEqualFilterRule<T> source)
: base(source)
{
}
/// <summary>
/// Determines if item is not equal to Value.
/// </summary>
@@ -18,13 +18,22 @@ namespace Microsoft.Management.UI.Internal
public class EqualsFilterRule<T> : SingleValueComparableValueFilterRule<T> where T : IComparable
{
/// <summary>
/// Initializes a new instance of the EqualsFilterRule class.
/// Initializes a new instance of the <see cref="EqualsFilterRule{T}"/> class.
/// </summary>
public EqualsFilterRule()
{
this.DisplayName = UICultureResources.FilterRule_Equals;
}
/// <summary>
/// Initializes a new instance of the <see cref="EqualsFilterRule{T}"/> class.
/// </summary>
/// <param name="source">The source to initialize from.</param>
public EqualsFilterRule(EqualsFilterRule<T> source)
: base(source)
{
}
/// <summary>
/// Determines if item is equal to Value.
/// </summary>
@@ -11,7 +11,7 @@ namespace Microsoft.Management.UI.Internal
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
[Serializable]
public abstract class FilterRule : IEvaluate
public abstract class FilterRule : IEvaluate, IDeepCloneable
{
/// <summary>
/// Gets a value indicating whether the FilterRule can be
@@ -35,12 +35,28 @@ namespace Microsoft.Management.UI.Internal
}
/// <summary>
/// Initializes a new instance of the FilterRule class.
/// Initializes a new instance of the <see cref="FilterRule"/> class.
/// </summary>
protected FilterRule()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="FilterRule"/> class.
/// </summary>
/// <param name="source">The source to initialize from.</param>
protected FilterRule(FilterRule source)
{
ArgumentNullException.ThrowIfNull(source);
this.DisplayName = source.DisplayName;
}
/// <inheritdoc cref="IDeepCloneable.DeepClone()" />
public object DeepClone()
{
return Activator.CreateInstance(this.GetType(), new object[] { this });
}
/// <summary>
/// Gets a value indicating whether the supplied item meets the
/// criteria specified by this rule.
@@ -2,10 +2,6 @@
// Licensed under the MIT License.
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace Microsoft.Management.UI.Internal
{
@@ -28,29 +24,7 @@ namespace Microsoft.Management.UI.Internal
public static FilterRule DeepCopy(this FilterRule rule)
{
ArgumentNullException.ThrowIfNull(rule);
#pragma warning disable SYSLIB0050
Debug.Assert(rule.GetType().IsSerializable, "rule is serializable");
#pragma warning disable SYSLIB0011
BinaryFormatter formatter = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.Clone));
#pragma warning restore SYSLIB0011
MemoryStream ms = new MemoryStream();
FilterRule copy = null;
try
{
formatter.Serialize(ms, rule);
ms.Position = 0;
copy = (FilterRule)formatter.Deserialize(ms);
#pragma warning restore SYSLIB0050
}
finally
{
ms.Close();
}
return copy;
return (FilterRule)rule.DeepClone();
}
}
}
@@ -56,7 +56,7 @@ namespace Microsoft.Management.UI.Internal
#region Ctor
/// <summary>
/// Initializes a new instance of the IsBetweenFilterRule class.
/// Initializes a new instance of the <see cref="IsBetweenFilterRule{T}"/> class.
/// </summary>
public IsBetweenFilterRule()
{
@@ -69,6 +69,20 @@ namespace Microsoft.Management.UI.Internal
this.EndValue.PropertyChanged += this.Value_PropertyChanged;
}
/// <summary>
/// Initializes a new instance of the <see cref="IsBetweenFilterRule{T}"/> class.
/// </summary>
/// <param name="source">The source to initialize from.</param>
public IsBetweenFilterRule(IsBetweenFilterRule<T> source)
: base(source)
{
this.StartValue = (ValidatingValue<T>)source.StartValue.DeepClone();
this.StartValue.PropertyChanged += this.Value_PropertyChanged;
this.EndValue = (ValidatingValue<T>)source.EndValue.DeepClone();
this.EndValue.PropertyChanged += this.Value_PropertyChanged;
}
#endregion Ctor
#region Public Methods
@@ -14,13 +14,22 @@ namespace Microsoft.Management.UI.Internal
public class IsEmptyFilterRule : FilterRule
{
/// <summary>
/// Initializes a new instance of the IsEmptyFilterRule class.
/// Initializes a new instance of the <see cref="IsEmptyFilterRule"/> class.
/// </summary>
public IsEmptyFilterRule()
{
this.DisplayName = UICultureResources.FilterRule_IsEmpty;
}
/// <summary>
/// Initializes a new instance of the <see cref="IsEmptyFilterRule"/> class.
/// </summary>
/// <param name="source">The source to initialize from.</param>
public IsEmptyFilterRule(IsEmptyFilterRule source)
: base(source)
{
}
/// <summary>
/// Gets a values indicating whether the supplied item is empty.
/// </summary>
@@ -18,13 +18,22 @@ namespace Microsoft.Management.UI.Internal
public class IsGreaterThanFilterRule<T> : SingleValueComparableValueFilterRule<T> where T : IComparable
{
/// <summary>
/// Initializes a new instance of the IsGreaterThanFilterRule class.
/// Initializes a new instance of the <see cref="IsGreaterThanFilterRule{T}"/> class.
/// </summary>
public IsGreaterThanFilterRule()
{
this.DisplayName = UICultureResources.FilterRule_GreaterThanOrEqual;
}
/// <summary>
/// Initializes a new instance of the <see cref="IsGreaterThanFilterRule{T}"/> class.
/// </summary>
/// <param name="source">The source to initialize from.</param>
public IsGreaterThanFilterRule(IsGreaterThanFilterRule<T> source)
: base(source)
{
}
/// <summary>
/// Determines if item is greater than Value.
/// </summary>
@@ -18,13 +18,22 @@ namespace Microsoft.Management.UI.Internal
public class IsLessThanFilterRule<T> : SingleValueComparableValueFilterRule<T> where T : IComparable
{
/// <summary>
/// Initializes a new instance of the IsLessThanFilterRule class.
/// Initializes a new instance of the <see cref="IsLessThanFilterRule{T}"/> class.
/// </summary>
public IsLessThanFilterRule()
{
this.DisplayName = UICultureResources.FilterRule_LessThanOrEqual;
}
/// <summary>
/// Initializes a new instance of the <see cref="IsLessThanFilterRule{T}"/> class.
/// </summary>
/// <param name="source">The source to initialize from.</param>
public IsLessThanFilterRule(IsLessThanFilterRule<T> source)
: base(source)
{
}
/// <summary>
/// Determines if item is less than Value.
/// </summary>
@@ -14,13 +14,22 @@ namespace Microsoft.Management.UI.Internal
public class IsNotEmptyFilterRule : IsEmptyFilterRule
{
/// <summary>
/// Initializes a new instance of the IsNotEmptyFilterRule class.
/// Initializes a new instance of the <see cref="IsNotEmptyFilterRule"/> class.
/// </summary>
public IsNotEmptyFilterRule()
{
this.DisplayName = UICultureResources.FilterRule_IsNotEmpty;
}
/// <summary>
/// Initializes a new instance of the <see cref="IsNotEmptyFilterRule"/> class.
/// </summary>
/// <param name="source">The source to initialize from.</param>
public IsNotEmptyFilterRule(IsNotEmptyFilterRule source)
: base(source)
{
}
/// <summary>
/// Gets a values indicating whether the supplied item is not empty.
/// </summary>
@@ -51,6 +51,14 @@ namespace Microsoft.Management.UI.Internal
}
}
/// <inheritdoc cref="IDeepCloneable.DeepClone()" />
public override object DeepClone()
{
// Instance is stateless.
// return this;
return new IsNotEmptyValidationRule();
}
#endregion Public Methods
internal static bool IsStringNotEmpty(string value)
@@ -29,6 +29,17 @@ namespace Microsoft.Management.UI.Internal
this.EvaluationResultInvalidated += this.PropertiesTextContainsFilterRule_EvaluationResultInvalidated;
}
/// <summary>
/// Initializes a new instance of the <see cref="PropertiesTextContainsFilterRule"/> class.
/// </summary>
/// <param name="source">The source to initialize from.</param>
public PropertiesTextContainsFilterRule(PropertiesTextContainsFilterRule source)
: base(source)
{
this.PropertyNames = new List<string>(source.PropertyNames);
this.EvaluationResultInvalidated += this.PropertiesTextContainsFilterRule_EvaluationResultInvalidated;
}
/// <summary>
/// Gets a collection of the names of properties to search in.
/// </summary>
@@ -82,6 +82,17 @@ namespace Microsoft.Management.UI.Internal
this.AvailableRules.DisplayNameConverter = new FilterRuleToDisplayNameConverter();
}
/// <summary>
/// Initializes a new instance of the <see cref="PropertyValueSelectorFilterRule{T}"/> class.
/// </summary>
/// <param name="source">The source to initialize from.</param>
public PropertyValueSelectorFilterRule(PropertyValueSelectorFilterRule<T> source)
: base(source)
{
this.PropertyName = source.PropertyName;
this.AvailableRules.DisplayNameConverter = new FilterRuleToDisplayNameConverter();
}
#endregion Ctor
#region Public Methods
@@ -40,7 +40,7 @@ namespace Microsoft.Management.UI.Internal
#region Ctor
/// <summary>
/// Creates a new SelectorFilterRule instance.
/// Initializes a new instance of the <see cref="SelectorFilterRule"/> class.
/// </summary>
public SelectorFilterRule()
{
@@ -48,6 +48,18 @@ namespace Microsoft.Management.UI.Internal
this.AvailableRules.SelectedValueChanged += this.AvailableRules_SelectedValueChanged;
}
/// <summary>
/// Initializes a new instance of the <see cref="SelectorFilterRule"/> class.
/// </summary>
/// <param name="source">The source to initialize from.</param>
public SelectorFilterRule(SelectorFilterRule source)
: base(source)
{
this.AvailableRules = (ValidatingSelectorValue<FilterRule>)source.AvailableRules.DeepClone();
this.AvailableRules.SelectedValueChanged += this.AvailableRules_SelectedValueChanged;
this.AvailableRules.SelectedValue.EvaluationResultInvalidated += this.SelectedValue_EvaluationResultInvalidated;
}
#endregion Ctor
#region Public Methods
@@ -86,8 +98,8 @@ namespace Microsoft.Management.UI.Internal
FilterRuleCustomizationFactory.FactoryInstance.TransferValues(oldValue, newValue);
FilterRuleCustomizationFactory.FactoryInstance.ClearValues(oldValue);
newValue.EvaluationResultInvalidated += this.SelectedValue_EvaluationResultInvalidated;
oldValue.EvaluationResultInvalidated -= this.SelectedValue_EvaluationResultInvalidated;
newValue.EvaluationResultInvalidated += this.SelectedValue_EvaluationResultInvalidated;
this.NotifyEvaluationResultInvalidated();
}
@@ -44,7 +44,7 @@ namespace Microsoft.Management.UI.Internal
#region Ctor
/// <summary>
/// Initializes a new instance of the SingleValueComparableValueFilterRule class.
/// Initializes a new instance of the <see cref="SingleValueComparableValueFilterRule{T}"/> class.
/// </summary>
protected SingleValueComparableValueFilterRule()
{
@@ -52,6 +52,17 @@ namespace Microsoft.Management.UI.Internal
this.Value.PropertyChanged += this.Value_PropertyChanged;
}
/// <summary>
/// Initializes a new instance of the <see cref="SingleValueComparableValueFilterRule{T}"/> class.
/// </summary>
/// <param name="source">The source to initialize from.</param>
protected SingleValueComparableValueFilterRule(SingleValueComparableValueFilterRule<T> source)
: base(source)
{
this.Value = (ValidatingValue<T>)source.Value.DeepClone();
this.Value.PropertyChanged += this.Value_PropertyChanged;
}
#endregion Ctor
private void Value_PropertyChanged(object sender, PropertyChangedEventArgs e)
@@ -18,13 +18,22 @@ namespace Microsoft.Management.UI.Internal
private static readonly string TextContainsWordsRegexPattern = WordBoundaryRegexPattern + TextContainsCharactersRegexPattern + WordBoundaryRegexPattern;
/// <summary>
/// Initializes a new instance of the TextContainsFilterRule class.
/// Initializes a new instance of the <see cref="TextContainsFilterRule"/> class.
/// </summary>
public TextContainsFilterRule()
{
this.DisplayName = UICultureResources.FilterRule_Contains;
}
/// <summary>
/// Initializes a new instance of the <see cref="TextContainsFilterRule"/> class.
/// </summary>
/// <param name="source">The source to initialize from.</param>
public TextContainsFilterRule(TextContainsFilterRule source)
: base(source)
{
}
/// <summary>
/// Determines if Value is contained within data.
/// </summary>
@@ -14,7 +14,7 @@ namespace Microsoft.Management.UI.Internal
public class TextDoesNotContainFilterRule : TextContainsFilterRule
{
/// <summary>
/// Initializes a new instance of the TextDoesNotContainFilterRule class.
/// Initializes a new instance of the <see cref="TextDoesNotContainFilterRule"/> class.
/// </summary>
public TextDoesNotContainFilterRule()
{
@@ -22,6 +22,15 @@ namespace Microsoft.Management.UI.Internal
this.DefaultNullValueEvaluation = true;
}
/// <summary>
/// Initializes a new instance of the <see cref="TextDoesNotContainFilterRule"/> class.
/// </summary>
/// <param name="source">The source to initialize from.</param>
public TextDoesNotContainFilterRule(TextDoesNotContainFilterRule source)
: base(source)
{
}
/// <summary>
/// Determines if Value is not contained within data.
/// </summary>
@@ -14,7 +14,7 @@ namespace Microsoft.Management.UI.Internal
public class TextDoesNotEqualFilterRule : TextEqualsFilterRule
{
/// <summary>
/// Initializes a new instance of the TextDoesNotEqualFilterRule class.
/// Initializes a new instance of the <see cref="TextDoesNotEqualFilterRule"/> class.
/// </summary>
public TextDoesNotEqualFilterRule()
{
@@ -22,6 +22,15 @@ namespace Microsoft.Management.UI.Internal
this.DefaultNullValueEvaluation = true;
}
/// <summary>
/// Initializes a new instance of the <see cref="TextDoesNotEqualFilterRule"/> class.
/// </summary>
/// <param name="source">The source to initialize from.</param>
public TextDoesNotEqualFilterRule(TextDoesNotEqualFilterRule source)
: base(source)
{
}
/// <summary>
/// Determines if data is not equal to Value.
/// </summary>
@@ -18,13 +18,22 @@ namespace Microsoft.Management.UI.Internal
private static readonly string TextEndsWithWordsRegexPattern = WordBoundaryRegexPattern + TextEndsWithCharactersRegexPattern;
/// <summary>
/// Initializes a new instance of the TextEndsWithFilterRule class.
/// Initializes a new instance of the <see cref="TextEndsWithFilterRule"/> class.
/// </summary>
public TextEndsWithFilterRule()
{
this.DisplayName = UICultureResources.FilterRule_TextEndsWith;
}
/// <summary>
/// Initializes a new instance of the <see cref="TextEndsWithFilterRule"/> class.
/// </summary>
/// <param name="source">The source to initialize from.</param>
public TextEndsWithFilterRule(TextEndsWithFilterRule source)
: base(source)
{
}
/// <summary>
/// Determines if data ends with Value.
/// </summary>
@@ -17,13 +17,22 @@ namespace Microsoft.Management.UI.Internal
private static readonly string TextEqualsCharactersRegexPattern = "^{0}$";
/// <summary>
/// Initializes a new instance of the TextEqualsFilterRule class.
/// Initializes a new instance of the <see cref="TextEqualsFilterRule"/> class.
/// </summary>
public TextEqualsFilterRule()
{
this.DisplayName = UICultureResources.FilterRule_Equals;
}
/// <summary>
/// Initializes a new instance of the <see cref="TextEqualsFilterRule"/> class.
/// </summary>
/// <param name="source">The source to initialize from.</param>
public TextEqualsFilterRule(TextEqualsFilterRule source)
: base(source)
{
}
/// <summary>
/// Determines if data is equal to Value.
/// </summary>
@@ -62,7 +62,7 @@ namespace Microsoft.Management.UI.Internal
}
/// <summary>
/// Initializes a new instance of the TextFilterRule class.
/// Initializes a new instance of the <see cref="TextFilterRule"/> class.
/// </summary>
protected TextFilterRule()
{
@@ -70,6 +70,17 @@ namespace Microsoft.Management.UI.Internal
this.CultureInvariant = false;
}
/// <summary>
/// Initializes a new instance of the <see cref="TextFilterRule"/> class.
/// </summary>
/// <param name="source">The source to initialize from.</param>
protected TextFilterRule(TextFilterRule source)
: base(source)
{
this.IgnoreCase = source.IgnoreCase;
this.CultureInvariant = source.CultureInvariant;
}
/// <summary>
/// Gets the current value and determines whether it should be evaluated as an exact match.
/// </summary>
@@ -18,13 +18,22 @@ namespace Microsoft.Management.UI.Internal
private static readonly string TextStartsWithWordsRegexPattern = TextStartsWithCharactersRegexPattern + WordBoundaryRegexPattern;
/// <summary>
/// Initializes a new instance of the TextStartsWithFilterRule class.
/// Initializes a new instance of the <see cref="TextStartsWithFilterRule"/> class.
/// </summary>
public TextStartsWithFilterRule()
{
this.DisplayName = UICultureResources.FilterRule_TextStartsWith;
}
/// <summary>
/// Initializes a new instance of the <see cref="TextStartsWithFilterRule"/> class.
/// </summary>
/// <param name="source">The source to initialize from.</param>
public TextStartsWithFilterRule(TextStartsWithFilterRule source)
: base(source)
{
}
/// <summary>
/// Determines if data starts with Value.
/// </summary>
@@ -0,0 +1,18 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// Defines a generalized method for creating a deep copy of an instance.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
public interface IDeepCloneable
{
/// <summary>
/// Creates a deep copy of the current instance.
/// </summary>
/// <returns>A new object that is a deep copy of the current instance.</returns>
object DeepClone();
}
}
@@ -20,6 +20,37 @@ namespace Microsoft.Management.UI.Internal
[Serializable]
public class ValidatingSelectorValue<T> : ValidatingValueBase
{
/// <summary>
/// Initializes a new instance of the <see cref="ValidatingSelectorValue{T}"/> class.
/// </summary>
public ValidatingSelectorValue()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ValidatingSelectorValue{T}"/> class.
/// </summary>
/// <param name="source">The source to initialize from.</param>
public ValidatingSelectorValue(ValidatingSelectorValue<T> source)
: base(source)
{
availableValues.EnsureCapacity(source.availableValues.Count);
if (typeof(IDeepCloneable).IsAssignableFrom(typeof(T)))
{
foreach (var value in source.availableValues)
{
availableValues.Add((T)((IDeepCloneable)value).DeepClone());
}
}
else
{
availableValues.AddRange(source.availableValues);
}
selectedIndex = source.selectedIndex;
displayNameConverter = source.displayNameConverter;
}
#region Properties
#region Consts
@@ -151,6 +182,12 @@ namespace Microsoft.Management.UI.Internal
#region Public Methods
/// <inheritdoc cref="IDeepCloneable.DeepClone()" />
public override object DeepClone()
{
return new ValidatingSelectorValue<T>(this);
}
#region Validate
/// <summary>
@@ -18,6 +18,23 @@ namespace Microsoft.Management.UI.Internal
[Serializable]
public class ValidatingValue<T> : ValidatingValueBase
{
/// <summary>
/// Initializes a new instance of the <see cref="ValidatingValue{T}"/> class.
/// </summary>
public ValidatingValue()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ValidatingValue{T}"/> class.
/// </summary>
/// <param name="source">The source to initialize from.</param>
public ValidatingValue(ValidatingValue<T> source)
: base(source)
{
value = source.Value is IDeepCloneable deepClone ? deepClone.DeepClone() : source.Value;
}
#region Properties
#region Value
@@ -50,6 +67,12 @@ namespace Microsoft.Management.UI.Internal
#region Public Methods
/// <inheritdoc cref="IDeepCloneable.DeepClone()" />
public override object DeepClone()
{
return new ValidatingValue<T>(this);
}
/// <summary>
/// Gets the raw value cast/transformed into
/// type T.
@@ -17,8 +17,29 @@ namespace Microsoft.Management.UI.Internal
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
[Serializable]
public abstract class ValidatingValueBase : IDataErrorInfo, INotifyPropertyChanged
public abstract class ValidatingValueBase : IDataErrorInfo, INotifyPropertyChanged, IDeepCloneable
{
/// <summary>
/// Initializes a new instance of the <see cref="ValidatingValueBase"/> class.
/// </summary>
protected ValidatingValueBase()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ValidatingValueBase"/> class.
/// </summary>
/// <param name="source">The source to initialize from.</param>
protected ValidatingValueBase(ValidatingValueBase source)
{
ArgumentNullException.ThrowIfNull(source);
validationRules.EnsureCapacity(source.validationRules.Count);
foreach (var rule in source.validationRules)
{
validationRules.Add((DataErrorInfoValidationRule)rule.DeepClone());
}
}
#region Properties
#region ValidationRules
@@ -130,6 +151,9 @@ namespace Microsoft.Management.UI.Internal
#region Public Methods
/// <inheritdoc cref="IDeepCloneable.DeepClone()" />
public abstract object DeepClone();
#region AddValidationRule
/// <summary>
@@ -10,7 +10,7 @@ namespace Microsoft.Management.UI.Internal
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
[Serializable]
public abstract class DataErrorInfoValidationRule
public abstract class DataErrorInfoValidationRule : IDeepCloneable
{
/// <summary>
/// When overridden in a derived class, performs validation checks on a value.
@@ -25,5 +25,8 @@ namespace Microsoft.Management.UI.Internal
/// A DataErrorInfoValidationResult object.
/// </returns>
public abstract DataErrorInfoValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo);
/// <inheritdoc cref="IDeepCloneable.DeepClone()" />
public abstract object DeepClone();
}
}