Ich habe ein Problem, bei dem ich eine Einstellungsstruktur für meine App erstellen möchte, die hinsichtlich Lokalisierung, Erweiterung und Gruppierung so optimal wie möglich sein muss. Ich möchte die Einstellungen je Entitätstyp gruppieren (Sie können sich das als Gruppierungseinstellungen pro Controller vorstellen). Die Einstellungen werden dem Benutzer angezeigt, so dass für jede Einstellung ein hübscher Titel und eine Beschreibung benötigt werden, die beide lokalisiert werden müssen. Neue Einstellungen werden nur von den Entwicklern eingeführt und eine Neukompilierung wird benötigt.Entwerfen einer Einstellungsstruktur
Was ich entwickelt habe, ist eine Klasse, die Einstellungen als statische Eigenschaften verfügbar macht, so dass sie leicht zugänglich sind, um in der gesamten Anwendung in einer statischen Weise verwendet werden. Die Einstellungen werden geladen, wenn die Klasse das erste Mal erstellt wird (was passiert, wenn die Einstellung angefordert wird), und ich verwende die Datenbank, um die Einstellungen zu speichern und sie mithilfe der Reflektion zur Laufzeit ihren entsprechenden Eigenschaften zuzuordnen.
Es sieht aus wie dieses
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
}
Jede Einstellung in DB als Kleinbuchstaben Version des Eigenschaftsnamen gespeichert (zum Laden außer Acht lassen wir den Fall). Dasselbe gilt für den Lokalisierungsstring, der beispielsweise als FirmSettings_ShowDocumentTaxStatement_Title und FirmSettings_ShowDocumentTaxStatement_Desc gespeichert wird. (Konvention)
Dieser Ansatz löst jedoch keine Gruppierung. In der Benutzeroberfläche ist eine Gruppierung von Einstellungen erforderlich, sodass die Rechnungseinstellungen in einer Gruppe angezeigt werden. Ich könnte ein Präfix für bestimmte Einstellungen einführen und dann basierend auf dem Präfix rendern (eine andere Konvention).
Mögen Sie diesen Ansatz? Wenn nicht, wie machst du das? Es gibt viele Konventionen in diesem Ansatz und das stört mich nur ein wenig.
K TBH, ich bin mir nicht wirklich sicher, ob ich die Schreibfrage beantworte ... –
Vielen Dank für Ihre Meinung zu Singleton, es lohnt sich, es auszuprobieren und zu versuchen, diese Route zu gehen. Ich habe eine neue Frage über das Problem des Spiels mit Singleton oder statischen Klassen geöffnet http://stackoverflow.com/questions/4382537/singleton-class-or-a-class-with-static-methods-in-asp-net-mvc- Anwendung – mare