鉴于Azure Cloud Service,是否可以使用<appSettings>
文件而不是将其存储在app.config
中?
我有一个项目:
appSettings
包含<add key="clientId" value="Dev"/>
,如cscfg
然后,两个Prod.cscfg
文件可以覆盖此设置,使其成为特定的天蓝色环境。例如,<ConfigurationSettings>
<Setting name="clientId" value="Prod" />
</ConfigurationSettings>
:
settings.setting
然后在Azure中我可以进一步自定义这些设置:
我可以切换为使用.field= f.select :sponsor_id, sponsors.map { |s| [s.name, s.id] }, {:class => "my-class"}
文件并仍允许azure正确连接覆盖吗?
答案 0 :(得分:0)
在玩了一段时间后,我决定提出一个包装类来处理这两种情况。
它的使用方式如下:
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>
//http://stackoverflow.com/questions/11548301/azure-configuration-settings-and-microsoft-windowsazure-cloudconfigurationmanage
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;
}