ConfigurationProperty
using System.ComponentModel;
using System.Reflection;
namespace System.Configuration
{
public sealed class ConfigurationProperty
{
internal static readonly ConfigurationValidatorBase s_nonEmptyStringValidator = new StringValidator(1);
private static readonly ConfigurationValidatorBase s_defaultValidatorInstance = new DefaultValidator();
internal const string DefaultCollectionPropertyName = "";
private TypeConverter _converter;
private volatile bool _isConfigurationElementType;
private volatile bool _isTypeInited;
private ConfigurationPropertyOptions _options;
public string Name { get; set; }
public string Description { get; set; }
internal string ProvidedName { get; set; }
internal bool IsConfigurationElementType {
get {
if (_isTypeInited)
return _isConfigurationElementType;
_isConfigurationElementType = typeof(ConfigurationElement).IsAssignableFrom(Type);
_isTypeInited = true;
return _isConfigurationElementType;
}
}
public Type Type { get; set; }
public object DefaultValue { get; set; }
public bool IsRequired => (_options & ConfigurationPropertyOptions.IsRequired) != ConfigurationPropertyOptions.None;
public bool IsKey => (_options & ConfigurationPropertyOptions.IsKey) != ConfigurationPropertyOptions.None;
public bool IsDefaultCollection => (_options & ConfigurationPropertyOptions.IsDefaultCollection) != ConfigurationPropertyOptions.None;
public bool IsTypeStringTransformationRequired => (_options & ConfigurationPropertyOptions.IsTypeStringTransformationRequired) != ConfigurationPropertyOptions.None;
public bool IsAssemblyStringTransformationRequired => (_options & ConfigurationPropertyOptions.IsAssemblyStringTransformationRequired) != ConfigurationPropertyOptions.None;
public bool IsVersionCheckRequired => (_options & ConfigurationPropertyOptions.IsVersionCheckRequired) != ConfigurationPropertyOptions.None;
public TypeConverter Converter {
get {
CreateConverter();
return _converter;
}
}
public ConfigurationValidatorBase Validator { get; set; }
internal string AddElementName { get; }
internal string RemoveElementName { get; }
internal string ClearElementName { get; }
public ConfigurationProperty(string name, Type type)
{
object defaultValue = null;
ConstructorInit(name, type, ConfigurationPropertyOptions.None, null, null, null);
if (type == typeof(string))
defaultValue = string.Empty;
else if (type.IsValueType) {
defaultValue = TypeUtil.CreateInstance(type);
}
SetDefaultValue(defaultValue);
}
public ConfigurationProperty(string name, Type type, object defaultValue)
: this(name, type, defaultValue, ConfigurationPropertyOptions.None)
{
}
public ConfigurationProperty(string name, Type type, object defaultValue, ConfigurationPropertyOptions options)
: this(name, type, defaultValue, null, null, options)
{
}
public ConfigurationProperty(string name, Type type, object defaultValue, TypeConverter typeConverter, ConfigurationValidatorBase validator, ConfigurationPropertyOptions options)
: this(name, type, defaultValue, typeConverter, validator, options, null)
{
}
public ConfigurationProperty(string name, Type type, object defaultValue, TypeConverter typeConverter, ConfigurationValidatorBase validator, ConfigurationPropertyOptions options, string description)
{
ConstructorInit(name, type, options, validator, typeConverter, description);
SetDefaultValue(defaultValue);
}
internal ConfigurationProperty(PropertyInfo info)
{
ConfigurationPropertyAttribute configurationPropertyAttribute = null;
DescriptionAttribute descriptionAttribute = null;
DefaultValueAttribute defaultValueAttribute = null;
TypeConverter converter = null;
ConfigurationValidatorBase configurationValidatorBase = null;
Attribute[] customAttributes = Attribute.GetCustomAttributes(info);
foreach (Attribute attribute in customAttributes) {
if (attribute is TypeConverterAttribute)
converter = TypeUtil.CreateInstance<TypeConverter>(((TypeConverterAttribute)attribute).ConverterTypeName);
else if (attribute is ConfigurationPropertyAttribute) {
configurationPropertyAttribute = (ConfigurationPropertyAttribute)attribute;
} else if (attribute is ConfigurationValidatorAttribute) {
if (configurationValidatorBase != null)
throw new ConfigurationErrorsException(System.SR.Format(System.SR.Validator_multiple_validator_attributes, info.Name));
ConfigurationValidatorAttribute configurationValidatorAttribute = (ConfigurationValidatorAttribute)attribute;
configurationValidatorAttribute.SetDeclaringType(info.DeclaringType);
configurationValidatorBase = configurationValidatorAttribute.ValidatorInstance;
} else if (attribute is DescriptionAttribute) {
descriptionAttribute = (DescriptionAttribute)attribute;
} else if (attribute is DefaultValueAttribute) {
defaultValueAttribute = (DefaultValueAttribute)attribute;
}
}
Type propertyType = info.PropertyType;
if (typeof(ConfigurationElementCollection).IsAssignableFrom(propertyType)) {
ConfigurationCollectionAttribute configurationCollectionAttribute = (Attribute.GetCustomAttribute(info, typeof(ConfigurationCollectionAttribute)) as ConfigurationCollectionAttribute) ?? (Attribute.GetCustomAttribute(propertyType, typeof(ConfigurationCollectionAttribute)) as ConfigurationCollectionAttribute);
if (configurationCollectionAttribute != null) {
if (!configurationCollectionAttribute.AddItemName.Contains(','))
AddElementName = configurationCollectionAttribute.AddItemName;
RemoveElementName = configurationCollectionAttribute.RemoveItemName;
ClearElementName = configurationCollectionAttribute.ClearItemsName;
}
}
ConstructorInit(configurationPropertyAttribute.Name, info.PropertyType, configurationPropertyAttribute.Options, configurationValidatorBase, converter, descriptionAttribute?.Description);
InitDefaultValueFromTypeInfo(configurationPropertyAttribute, defaultValueAttribute);
}
private void ConstructorInit(string name, Type type, ConfigurationPropertyOptions options, ConfigurationValidatorBase validator, TypeConverter converter, string description)
{
if (typeof(ConfigurationSection).IsAssignableFrom(type))
throw new ConfigurationErrorsException(System.SR.Format(System.SR.Config_properties_may_not_be_derived_from_configuration_section, name));
ProvidedName = name;
if ((options & ConfigurationPropertyOptions.IsDefaultCollection) != 0 && string.IsNullOrEmpty(name))
name = "";
else
ValidatePropertyName(name);
Name = name;
Description = description;
Type = type;
_options = options;
Validator = validator;
_converter = converter;
if (Validator == null)
Validator = s_defaultValidatorInstance;
else if (!Validator.CanValidate(Type)) {
throw new ConfigurationErrorsException(System.SR.Format(System.SR.Validator_does_not_support_prop_type, Name));
}
}
private static void ValidatePropertyName(string name)
{
if (string.IsNullOrEmpty(name))
throw new ArgumentException(System.SR.String_null_or_empty, "name");
if (BaseConfigurationRecord.IsReservedAttributeName(name))
throw new ArgumentException(System.SR.Format(System.SR.Property_name_reserved, name));
}
private void SetDefaultValue(object value)
{
if (!ConfigurationElement.IsNullOrNullProperty(value)) {
if (!Type.IsInstanceOfType(value)) {
if (!Converter.CanConvertFrom(value.GetType()))
throw new ConfigurationErrorsException(System.SR.Format(System.SR.Default_value_wrong_type, Name));
value = Converter.ConvertFrom(value);
}
Validate(value);
DefaultValue = value;
}
}
private void InitDefaultValueFromTypeInfo(ConfigurationPropertyAttribute configurationProperty, DefaultValueAttribute defaultValueAttribute)
{
object obj = configurationProperty.DefaultValue;
if (ConfigurationElement.IsNullOrNullProperty(obj))
obj = defaultValueAttribute?.Value;
if (obj is string && Type != typeof(string))
try {
obj = Converter.ConvertFromInvariantString((string)obj);
} catch (Exception ex) {
throw new ConfigurationErrorsException(System.SR.Format(System.SR.Default_value_conversion_error_from_string, Name, ex.Message));
}
if (ConfigurationElement.IsNullOrNullProperty(obj)) {
if (Type == typeof(string))
obj = string.Empty;
else if (Type.IsValueType) {
obj = TypeUtil.CreateInstance(Type);
}
}
SetDefaultValue(obj);
}
internal object ConvertFromString(string value)
{
try {
return Converter.ConvertFromInvariantString(value);
} catch (Exception ex) {
throw new ConfigurationErrorsException(System.SR.Format(System.SR.Top_level_conversion_error_from_string, Name, ex.Message));
}
}
internal string ConvertToString(object value)
{
try {
if (!(Type == typeof(bool)))
return Converter.ConvertToInvariantString(value);
return ((bool)value) ? "true" : "false";
} catch (Exception ex) {
throw new ConfigurationErrorsException(System.SR.Format(System.SR.Top_level_conversion_error_to_string, Name, ex.Message));
}
}
internal void Validate(object value)
{
try {
Validator.Validate(value);
} catch (Exception ex) {
throw new ConfigurationErrorsException(System.SR.Format(System.SR.Top_level_validation_error, Name, ex.Message), ex);
}
}
private void CreateConverter()
{
if (_converter == null) {
if (Type.IsEnum)
_converter = new GenericEnumConverter(Type);
else if (!Type.IsSubclassOf(typeof(ConfigurationElement))) {
_converter = TypeDescriptor.GetConverter(Type);
if (_converter == null || !_converter.CanConvertFrom(typeof(string)) || !_converter.CanConvertTo(typeof(string)))
throw new ConfigurationErrorsException(System.SR.Format(System.SR.No_converter, Name, Type.Name));
}
}
}
}
}