Beispiel #1
0
        public void Initialize(Func <string, SettingValue> getSetting, string serverDataDir, ResourceType type, string resourceName, bool throwIfThereIsNoSetMethod)
        {
            foreach (var property in GetConfigurationProperties())
            {
                if (property.Info.SetMethod == null)
                {
                    if (throwIfThereIsNoSetMethod)
                    {
                        throw new InvalidOperationException($"No set method available for '{property.Info.Name}' property.Info.");
                    }

                    continue;
                }

                TimeUnitAttribute timeUnit = property.TimeUnitAttribute;
                SizeUnitAttribute sizeUnit = property.SizeUnitAttribute;

                var configuredValueSet      = false;
                var setDefaultValueIfNeeded = true;

                ConfigurationEntryAttribute previousAttribute = null;

                foreach (var entry in property.Info.GetCustomAttributes <ConfigurationEntryAttribute>().OrderBy(order => order.Order))
                {
                    if (previousAttribute != null && previousAttribute.Scope != entry.Scope)
                    {
                        throw new InvalidOperationException($"All ConfigurationEntryAttribute for {property.Info.Name} must have the same Scope");
                    }

                    previousAttribute = entry;

                    var settingValue = getSetting(entry.Key);

                    if (type != ResourceType.Server && entry.Scope == ConfigurationEntryScope.ServerWideOnly && settingValue.CurrentValue != null)
                    {
                        throw new InvalidOperationException($"Configuration '{entry.Key}' can only be set at server level.");
                    }

                    string value = null;

                    if (settingValue.KeyExistsInDatabaseRecord)
                    {
                        value = settingValue.CurrentValue;

                        if (value == null && property.Info.Type() == typeof(PathSetting))
                        {
                            // for backward compatibility purposes let's ignore null on PathSetting and default to server value - RavenDB-15384
                            value = settingValue.ServerValue;
                        }
                    }
                    else if (settingValue.KeyExistsInServerSettings)
                    {
                        value = settingValue.ServerValue;
                    }

                    setDefaultValueIfNeeded &= entry.SetDefaultValueIfNeeded;

                    if (value == null)
                    {
                        continue;
                    }

                    value = value.Trim();

                    try
                    {
                        var minValue = property.MinValueAttribute;

                        if (minValue == null)
                        {
                            if (property.Info.PropertyType.IsEnum)
                            {
                                object parsedValue;
                                try
                                {
                                    parsedValue = Enum.Parse(property.Info.PropertyType, value, true);
                                }
                                catch (ArgumentException)
                                {
                                    throw new ConfigurationEnumValueException(value, property.Info.PropertyType);
                                }

                                property.Info.SetValue(this, parsedValue);
                            }
                            else if (property.Info.PropertyType == typeof(string[]))
                            {
                                var values = SplitValue(value);

                                property.Info.SetValue(this, values);
                            }
                            else if (property.Info.PropertyType.IsArray && property.Info.PropertyType.GetElementType().IsEnum)
                            {
                                var values = SplitValue(value)
                                             .Select(item => Enum.Parse(property.Info.PropertyType.GetElementType(), item, ignoreCase: true))
                                             .ToArray();

                                var enumValues = Array.CreateInstance(property.Info.PropertyType.GetElementType(), values.Length);
                                Array.Copy(values, enumValues, enumValues.Length);

                                property.Info.SetValue(this, enumValues);
                            }
                            else if (property.Info.PropertyType == typeof(HashSet <string>))
                            {
                                var hashSet = new HashSet <string>(SplitValue(value), StringComparer.OrdinalIgnoreCase);

                                property.Info.SetValue(this, hashSet);
                            }
                            else if (property.Info.PropertyType == typeof(UriSetting[]))
                            {
                                var          values   = SplitValue(value);
                                UriSetting[] settings = new UriSetting[values.Length];
                                for (var i = 0; i < values.Length; i++)
                                {
                                    settings[i] = new UriSetting(values[i]);
                                }
                                property.Info.SetValue(this, settings);
                            }
                            else if (timeUnit != null)
                            {
                                property.Info.SetValue(this, new TimeSetting(Convert.ToInt64(value), timeUnit.Unit));
                            }
                            else if (sizeUnit != null)
                            {
                                property.Info.SetValue(this, new Size(Convert.ToInt64(value), sizeUnit.Unit));
                            }
                            else
                            {
                                var t = Nullable.GetUnderlyingType(property.Info.PropertyType) ?? property.Info.PropertyType;

                                if (property.Info.PropertyType == typeof(PathSetting))
                                {
                                    property.Info.SetValue(this,
                                                           settingValue.CurrentValue != null
                                            ? new PathSetting(Convert.ToString(value), serverDataDir)
                                            : new PathSetting(Convert.ToString(value), type, resourceName));
                                }
                                else if (property.Info.PropertyType == typeof(PathSetting[]))
                                {
                                    var paths = SplitValue(value);

                                    property.Info.SetValue(this,
                                                           settingValue.CurrentValue != null
                                            ? paths.Select(x => new PathSetting(Convert.ToString(x), serverDataDir)).ToArray()
                                            : paths.Select(x => new PathSetting(Convert.ToString(x), type, resourceName)).ToArray());
                                }
                                else if (t == typeof(UriSetting))
                                {
                                    property.Info.SetValue(this, new UriSetting(value));
                                }
                                else
                                {
                                    var safeValue = Convert.ChangeType(value, t);
                                    property.Info.SetValue(this, safeValue);
                                }
                            }
                        }
                        else
                        {
                            if (property.Info.PropertyType == typeof(int) ||
                                property.Info.PropertyType == typeof(int?))
                            {
                                property.Info.SetValue(this, Math.Max(Convert.ToInt32(value), minValue.Int32Value));
                            }
                            else if (property.Info.PropertyType == typeof(Size) ||
                                     property.Info.PropertyType == typeof(Size?))
                            {
                                property.Info.SetValue(this, new Size(Math.Max(Convert.ToInt32(value), minValue.Int32Value), sizeUnit.Unit));
                            }
                            else if (property.Info.PropertyType == typeof(TimeSetting) ||
                                     property.Info.PropertyType == typeof(TimeSetting?))
                            {
                                property.Info.SetValue(this, new TimeSetting(Math.Max(Convert.ToInt32(value), minValue.Int32Value), timeUnit.Unit));
                            }
                            else
                            {
                                throw new NotSupportedException("Min value for " + property.Info.PropertyType + " is not supported. Property name: " + property.Info.Name);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        throw new InvalidOperationException($"Could not set '{entry.Key}' configuration setting value.", e);
                    }

                    configuredValueSet = true;
                    break;
                }

                if (configuredValueSet || setDefaultValueIfNeeded == false)
                {
                    continue;
                }

                var defaultValueAttribute = property.DefaultValueAttribute;

                if (defaultValueAttribute == null)
                {
                    throw new InvalidOperationException($"Property '{property.Info.Name}' does not have a default value attribute");
                }

                var defaultValue = defaultValueAttribute.Value;

                if (DefaultValueSetInConstructor.Equals(defaultValue))
                {
                    continue;
                }

                if (timeUnit != null && defaultValue != null)
                {
                    property.Info.SetValue(this, new TimeSetting(Convert.ToInt64(defaultValue), timeUnit.Unit));
                }
                else if (sizeUnit != null && defaultValue != null)
                {
                    property.Info.SetValue(this, new Size(Convert.ToInt64(defaultValue), sizeUnit.Unit));
                }
                else
                {
                    if (property.Info.PropertyType == typeof(PathSetting) && defaultValue != null)
                    {
                        property.Info.SetValue(this, new PathSetting(Convert.ToString(defaultValue), type, resourceName));
                    }
                    else if (property.Info.PropertyType == typeof(string[]) && defaultValue is string defaultValueAsString1)
                    {
                        var values = SplitValue(defaultValueAsString1);
                        property.Info.SetValue(this, values);
                    }
                    else if (property.Info.PropertyType.IsArray && property.Info.PropertyType.GetElementType().IsEnum&& defaultValue is string defaultValueAsString2)
                    {
                        var values = SplitValue(defaultValueAsString2)
                                     .Select(item => Enum.Parse(property.Info.PropertyType.GetElementType(), item, ignoreCase: true))
                                     .ToArray();

                        var enumValues = Array.CreateInstance(property.Info.PropertyType.GetElementType(), values.Length);
                        Array.Copy(values, enumValues, enumValues.Length);

                        property.Info.SetValue(this, enumValues);
                    }
                    else
                    {
                        property.Info.SetValue(this, defaultValue);
                    }
                }
            }

            Initialized = true;
        }
Beispiel #2
0
        public void Initialize(Func <string, SettingValue> getSetting, string serverDataDir, ResourceType type, string resourceName, bool throwIfThereIsNoSetMethod)
        {
            foreach (var property in GetConfigurationProperties())
            {
                if (property.SetMethod == null)
                {
                    if (throwIfThereIsNoSetMethod)
                    {
                        throw new InvalidOperationException($"No set method available for '{property.Name}' property.");
                    }

                    continue;
                }

                ValidateProperty(property);

                TimeUnitAttribute timeUnit = null;
                SizeUnitAttribute sizeUnit = null;

                if (property.PropertyType == typeof(TimeSetting) ||
                    property.PropertyType == typeof(TimeSetting?))
                {
                    timeUnit = property.GetCustomAttribute <TimeUnitAttribute>();
                    Debug.Assert(timeUnit != null);
                }
                else if (property.PropertyType == typeof(Size) ||
                         property.PropertyType == typeof(Size?))
                {
                    sizeUnit = property.GetCustomAttribute <SizeUnitAttribute>();
                    Debug.Assert(sizeUnit != null);
                }

                var configuredValueSet      = false;
                var setDefaultValueOfNeeded = true;

                ConfigurationEntryAttribute previousAttribute = null;

                foreach (var entry in property.GetCustomAttributes <ConfigurationEntryAttribute>().OrderBy(order => order.Order))
                {
                    if (previousAttribute != null && previousAttribute.Scope != entry.Scope)
                    {
                        throw new InvalidOperationException($"All ConfigurationEntryAttribute for {property.Name} must have the same Scope");
                    }

                    previousAttribute = entry;
                    var settingValue = getSetting(entry.Key);
                    if (type != ResourceType.Server && entry.Scope == ConfigurationEntryScope.ServerWideOnly && settingValue.CurrentValue != null)
                    {
                        throw new InvalidOperationException($"Configuration '{entry.Key}' can only be set at server level.");
                    }

                    var value = settingValue.CurrentValue ?? settingValue.ServerValue;
                    setDefaultValueOfNeeded &= entry.SetDefaultValueIfNeeded;

                    if (value == null)
                    {
                        continue;
                    }

                    value = value.Trim();

                    try
                    {
                        var minValue = property.GetCustomAttribute <MinValueAttribute>();

                        if (minValue == null)
                        {
                            if (property.PropertyType.GetTypeInfo().IsEnum)
                            {
                                object parsedValue;
                                try
                                {
                                    parsedValue = Enum.Parse(property.PropertyType, value, true);
                                }
                                catch (ArgumentException)
                                {
                                    throw new ConfigurationEnumValueException(value, property.PropertyType);
                                }

                                property.SetValue(this, parsedValue);
                            }
                            else if (property.PropertyType == typeof(string[]))
                            {
                                var values = SplitValue(value);

                                property.SetValue(this, values);
                            }
                            else if (property.PropertyType == typeof(HashSet <string>))
                            {
                                var hashSet = new HashSet <string>(SplitValue(value), StringComparer.OrdinalIgnoreCase);

                                property.SetValue(this, hashSet);
                            }
                            else if (timeUnit != null)
                            {
                                property.SetValue(this, new TimeSetting(Convert.ToInt64(value), timeUnit.Unit));
                            }
                            else if (sizeUnit != null)
                            {
                                property.SetValue(this, new Size(Convert.ToInt64(value), sizeUnit.Unit));
                            }
                            else
                            {
                                var t = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType;

                                if (property.PropertyType == typeof(PathSetting))
                                {
                                    property.SetValue(this,
                                                      settingValue.CurrentValue != null
                                            ? new PathSetting(Convert.ToString(value), serverDataDir)
                                            : new PathSetting(Convert.ToString(value), type, resourceName));
                                }
                                else if (property.PropertyType == typeof(PathSetting[]))
                                {
                                    var paths = SplitValue(value);

                                    property.SetValue(this,
                                                      settingValue.CurrentValue != null
                                            ? paths.Select(x => new PathSetting(Convert.ToString(x), serverDataDir)).ToArray()
                                            : paths.Select(x => new PathSetting(Convert.ToString(x), type, resourceName)).ToArray());
                                }
                                else if (t == typeof(UriSetting))
                                {
                                    property.SetValue(this, new UriSetting(value));
                                }
                                else
                                {
                                    var safeValue = Convert.ChangeType(value, t);
                                    property.SetValue(this, safeValue);
                                }
                            }
                        }
                        else
                        {
                            if (property.PropertyType == typeof(int) ||
                                property.PropertyType == typeof(int?))
                            {
                                property.SetValue(this, Math.Max(Convert.ToInt32(value), minValue.Int32Value));
                            }
                            else if (property.PropertyType == typeof(Size) ||
                                     property.PropertyType == typeof(Size?))
                            {
                                property.SetValue(this, new Size(Math.Max(Convert.ToInt32(value), minValue.Int32Value), sizeUnit.Unit));
                            }
                            else
                            {
                                throw new NotSupportedException("Min value for " + property.PropertyType + " is not supported. Property name: " + property.Name);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        throw new InvalidOperationException($"Could not set '{entry.Key}' configuration setting value.", e);
                    }

                    configuredValueSet = true;
                    break;
                }

                if (configuredValueSet || setDefaultValueOfNeeded == false)
                {
                    continue;
                }

                var defaultValueAttribute = property.GetCustomAttribute <DefaultValueAttribute>();

                if (defaultValueAttribute == null)
                {
                    throw new InvalidOperationException($"Property '{property.Name}' does not have a default value attribute");
                }

                var defaultValue = defaultValueAttribute.Value;

                if (DefaultValueSetInConstructor.Equals(defaultValue))
                {
                    continue;
                }

                if (timeUnit != null && defaultValue != null)
                {
                    property.SetValue(this, new TimeSetting(Convert.ToInt64(defaultValue), timeUnit.Unit));
                }
                else if (sizeUnit != null && defaultValue != null)
                {
                    property.SetValue(this, new Size(Convert.ToInt64(defaultValue), sizeUnit.Unit));
                }
                else
                {
                    if (property.PropertyType == typeof(PathSetting) && defaultValue != null)
                    {
                        property.SetValue(this, new PathSetting(Convert.ToString(defaultValue), type, resourceName));
                    }
                    else if (property.PropertyType == typeof(string[]) && defaultValue is string defaultValueAsString)
                    {
                        var values = SplitValue(defaultValueAsString);
                        property.SetValue(this, values);
                    }
                    else
                    {
                        property.SetValue(this, defaultValue);
                    }
                }
            }

            Initialized = true;
        }