Azure 云服务 - settings.setting

Azure Cloud Service - settings.setting

给定 Azure 云服务,是否可以使用 settings.setting 文件而不是将它们存储在 <appSettings> 中?

我有一个这样的项目:

app.config 包含一个 appSettings<add key="clientId" value="Dev"/>

然后两个 cscfg 文件可以覆盖此设置以特定于 azure 环境。例如,Prod.cscfg:

<ConfigurationSettings>
  <Setting name="clientId" value="Prod" />
</ConfigurationSettings>

然后在 Azure 中我可以进一步自定义这些设置:

我可以切换到使用 settings.setting 文件并仍然允许 azure 正确连接覆盖吗?

玩了一会儿之后,我决定想出一个包装器 class 来处理这两种情况。

是这样使用的:

public class Example
{
     private readonly ICloudSettingsProvider _cloudSettingsProvider;

     public void DoWork(){
         var setting = __cloudSettingsProvider.GetConfigurationSetting(
                        () => Properties.Setting.Default.ExampleConfiguration);

     }
}

实施:

public class CloudSettingsProvider : ICloudSettingsProvider
{
    public T GetConfigurationSetting<T>(Expression<Func<T>> setting)
    {
        Guard.ArgumentNotNull(setting, "setting");

        var settingNames = new List<string>();
        T settingDefaultValue;

        #region Parse settingNames / settingDefaultValue from setting Expression
        try
        {
            var memberExpression = (MemberExpression) setting.Body;

            //////Setting Name
            var settingName = memberExpression.Member.Name;

            if (string.IsNullOrEmpty(settingName))
                throw new Exception("Failed to get Setting Name (ie Property Name) from Expression");

            settingNames.Add(settingName);

            //////Setting Full Name
            var memberReflectedType = memberExpression.Member.ReflectedType;

            if (null != memberReflectedType)
                //we can use the settings full namespace as a search candidate as well
                settingNames.Add(memberReflectedType.FullName + "." + settingName);

            //////Setting Default Value
            settingDefaultValue = setting.Compile().Invoke();
        }
        catch (Exception e)
        {
            #region Wrap and Throw
            throw new Exception("Failed to parse Setting expression.  " +
                                "Expression should be like [() => Properties.Setting.Default.Foo]: " + e.Message,
                                e);
            #endregion
        }
        #endregion

        return GetConfigurationSettingInternal(
            settingDefaultValue,
            settingNames.ToArray());
    }      

    private T GetConfigurationSettingInternal<T>(T defaultvalue = default(T), params string[] configurationSettingNames)

    {
        Guard.ArgumentNotNullOrEmptyEnumerable(configurationSettingNames, "configurationSettingNames");

        //function for converting a string setting found in the 
        //<appConfig> or azure config to type T
        var conversionFunc = new Func<string, T>(setting =>
        {
            if (typeof(T).IsEnum)
                return (T)Enum.Parse(typeof(T), setting);

            if (!typeof(T).IsClass || typeof(T) == typeof(string))
                //value type
                return (T)Convert.ChangeType(setting, typeof(T));

            //dealing with a complex custom type, so let's assume it's
            //been serialized into xml. 
            return
                setting
                    .UnescapeXml()
                    .FromXml<T>();
        });


        ///////////////
        // Note: RoleEnvironment isn't always available in Unit Tests
        //   Fixing this by putting a general try/catch and returning the defaultValue
        //////////////
        try
        {
            if (!RoleEnvironment.IsAvailable)
            {
                //Check the <appSettings> element.
                var appConfigValue =
                    configurationSettingNames
                        .Select(name => ConfigurationManager.AppSettings[name])
                        .FirstOrDefault(value => !string.IsNullOrEmpty(value));

                return !string.IsNullOrEmpty(appConfigValue)
                    ? conversionFunc(appConfigValue)
                    : defaultvalue;

            }

            //Note: RoleEnvironment will fallback to <appConfig>
            //
            var azureConfigValue =
                configurationSettingNames
                        .Select(name => RoleEnvironment.GetConfigurationSettingValue(name))
                        .FirstOrDefault(value => !string.IsNullOrEmpty(value));

            return !string.IsNullOrEmpty(azureConfigValue)
                    ? conversionFunc(azureConfigValue)
                    : defaultvalue;

        }
        catch (InvalidCastException e)
        {
            _Logger.Warning(
                string.Format(
                    "InvalidCastException getting configuration setting [{0}]." +
                    "This generally means the value entered is of the wrong type (ie " +
                    "it wants an Int, but the config value has non-numeric characters: {1}",
                        configurationSettingNames, e.Message), e);
        }
        catch (Exception e)
        {
            _Logger.Warning(
                string.Format(
                    "Unhandled Exception getting configuration setting [{0}]: {1}",
                        configurationSettingNames, e.Message), e);
        }

        //If we are here, we hit an exception so return default value
        return defaultvalue;
    }