//------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------------------------ namespace System.ServiceModel.Configuration { using System; using System.Configuration; [AttributeUsage(AttributeTargets.Property)] internal sealed class StandardRuntimeFlagEnumValidatorAttribute : ConfigurationValidatorAttribute { Type enumType; Type validatorType; public StandardRuntimeFlagEnumValidatorAttribute(Type enumType) { StandardRuntimeFlagEnumValidatorAttribute.ValidateFlagEnumType(enumType); this.EnumType = enumType; } public Type EnumType { get { return this.enumType; } set { StandardRuntimeFlagEnumValidatorAttribute.ValidateFlagEnumType(value); this.enumType = value; } } static bool IsPowerOfTwo(int value) { return value > 0 && (value & (value - 1)) == 0; } internal static void ValidateFlagEnumType(Type value) { if (value == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("EnumType"); } bool hasFlags = value.GetCustomAttributes(typeof(FlagsAttribute), true).Length > 0; if (!value.IsEnum || !hasFlags) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("EnumType", SR.GetString(SR.FlagEnumTypeExpected, value)); } int[] values = (int[])Enum.GetValues(value); if (values != null && values.Length > 0) { for (int i = 0; i < values.Length; i++) { if (values[i] != 0 && !IsPowerOfTwo(values[i])) { if (!StandardRuntimeFlagEnumValidatorAttribute.IsCombinedValue(values[i], values, i - 1)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("EnumType", SR.GetString(SR.InvalidFlagEnumType)); } } } } } internal static bool IsCombinedValue(int combinedValue, int[] allowedValues, int startPosition) { int n = startPosition; while (n >= 0 && combinedValue > 0) { if ((combinedValue & allowedValues[n]) == allowedValues[n]) { combinedValue -= allowedValues[n]; } n--; } return combinedValue == 0; } private void EnsureValidatorType() { if (this.validatorType == null) { validatorType = typeof(StandardRuntimeFlagEnumValidator<>).MakeGenericType(new System.Type[] { this.enumType }); } } public override ConfigurationValidatorBase ValidatorInstance { get { this.EnsureValidatorType(); return (ConfigurationValidatorBase)Activator.CreateInstance(validatorType, null); } } } }