私は、ローカリゼーション、拡張、グループ化という点でできるだけ最適なものにする必要があるアプリケーションの設定構造を設計したいという問題がありました。エンティティタイプごとの設定をグループ化する必要があります(コントローラごとのグループ化設定と考えることができます)。設定はユーザーに表示されるので、それぞれの設定にはかなりのタイトルと説明が必要で、どちらもローカライズする必要があります。新しい設定は開発者によってのみ導入され、再コンパイルが必要になります。設定構造を設計する
私が思い描いたのは、静的なプロパティとして設定を公開するクラスであり、静的な方法でアプリケーション全体に簡単にアクセスできるようになっています。設定は、クラスの構築時に初めてロードされ(設定が要求されたときに実行されます)、データベースを使用して設定を保存し、リフレクションを使用して実行時に対応するプロパティに割り当てます。それは、この
public class FirmSettings
{
private static IFirmSettingsRepository _repository { get; set; }
public static bool ShowInvoicePaymentDetails { get; set; }
public static bool ShowInvoiceDiscountValue { get; set; }
public static bool ShowDocumentComment { get; set; }
public static bool ShowDocumentTaxStatement { get; set; }
public static bool ShowDocumentAuthor { get; set; }
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref = "FirmSettings" /> class.
/// </summary>
static FirmSettings()
{
Load();
}
#endregion
#region Load Settings
public static void Load()
{
_repository = MvcApplication.Container.Get<IFirmSettingsRepository>();
Type settingsType = typeof (FirmSettings);
//------------------------------------------------------------
// Enumerate through individual settings nodes
//------------------------------------------------------------
StringDictionary dic = _repository.LoadSettings();
if (dic == null)
{
Save(); // prepares the settings with blank settings
dic = _repository.LoadSettings(); // reload
}
foreach (string key in dic.Keys)
{
//------------------------------------------------------------
// Extract the setting's name/value pair
//------------------------------------------------------------
string name = key;
string value = dic[key];
//------------------------------------------------------------
// Enumerate through public properties of this instance
//------------------------------------------------------------
foreach (PropertyInfo propertyInformation in settingsType.GetProperties(BindingFlags.Public |
BindingFlags.Static))
{
//------------------------------------------------------------
// Determine if configured setting matches current setting based on name
//------------------------------------------------------------
if (propertyInformation.Name.Equals(name, StringComparison.OrdinalIgnoreCase))
{
//------------------------------------------------------------
// Attempt to apply configured setting
//------------------------------------------------------------
try
{
if (propertyInformation.CanWrite)
{
propertyInformation.SetValue(typeof (FirmSettings),
Convert.ChangeType(value, propertyInformation.PropertyType,
CultureInfo.CurrentCulture), null);
}
}
catch
{
// TODO: Log exception to a common logging framework?
}
break;
}
}
}
// perform resave if there are any new settings
Save();
}
#endregion
#region Save settings
/// <summary>
/// Saves the settings to disk.
/// </summary>
public static void Save()
{
StringDictionary dic = new StringDictionary();
Type settingsType = typeof (FirmSettings);
//------------------------------------------------------------
// Enumerate through settings properties
//------------------------------------------------------------
foreach (PropertyInfo propertyInformation in settingsType.GetProperties(BindingFlags.Public |
BindingFlags.Static))
{
//------------------------------------------------------------
// Extract property value and its string representation
//------------------------------------------------------------
object propertyValue = propertyInformation.GetValue(typeof (FirmSettings), null);
string valueAsString;
//------------------------------------------------------------
// Format null/default property values as empty strings
//------------------------------------------------------------
if (propertyValue == null || propertyValue.Equals(Int32.MinValue) || propertyValue.Equals(Single.MinValue))
{
valueAsString = String.Empty;
}
else
{
valueAsString = propertyValue.ToString();
}
//------------------------------------------------------------
// Write property name/value pair
//------------------------------------------------------------
dic.Add(propertyInformation.Name, valueAsString);
}
_repository.SaveSettings(dic);
}
#endregion
}
のように見えます
各設定は(読み込みのために私たちはケースを無視する)プロパティ名の小文字バージョンとしてDBに格納されます。ローカライゼーション文字列は、たとえばFirmSettings_ShowDocumentTaxStatement_TitleとFirmSettings_ShowDocumentTaxStatement_Descのように格納されます。
このアプローチではグループ化は解決されません。 UIでは、何らかの種類の設定が必要になるため、請求書の設定がグループに表示されます。私は特定の設定のプレフィックスを導入し、プレフィックスに基づいてそれをレンダリングすることができます(もう1つのコンベンション)。
この方法が好きですか?そうでない場合、どうやってそれをしますか?このアプローチにはたくさんの慣習がありますが、それは私を悩ますことです、ほんの少しです。
K TBH、書き込み質問に答えるかどうかわからない... –
シングルトンについてのご意見ありがとうございました。私は実際にシングルトンクラスや静的クラスを使ってconccurency問題に関する新しい質問を開きましたhttp://stackoverflow.com/questions/4382537/singleton-class-or-a-class-with-static-methods-in-asp-net-mvc-応用 – mare