Das Serialisieren und Deserialisieren eines Delegierten ist normalerweise keine gute Idee, da dies leicht zu ernsthaften Sicherheitsbedenken führt (siehe arbitrary code execution).
Stattdessen würde ich einen enum
oder ähnlichen serialisierbaren Typ empfehlen, der eine Anzahl von statisch definierten Funktionen identifiziert und zwischen ihnen konvertiert. Etwas wie folgt aus:
public enum FeedbackAction
{
Console,
Trace,
...
}
public static class FeedbackActions
{
public static void Console(string text) { ... }
public static void Trace(string text) { ... }
public static Action<string> GetAction(FeedbackAction action)
{
switch (action)
{
case FeedbackAction.Console:
return Console;
case FeedbackAction.Trace:
return Trace;
default:
throw new ArgumentException("Invalid feedback action.", nameof(action));
}
}
}
Nun, wenn Sie versuchen, die App-Einstellung zu verwenden, nur FeedbackActions.GetAction
rufen zwischen enum
Werten und den entsprechenden Action<string>
zu konvertieren.
Zum Beispiel:
public static class Feedback
{
public static Action<string> feedbackAction;
public static object syncLock = new object();
public static void ProvideFeedback(string text)
{
if (feedbackAction == null)
{
// synchronize to avoid duplicate calls
lock (syncLock)
{
if (feedbackAction == null)
{
var value = ConfigurationManager.AppSettings["FeedbackAction"];
feedbackAction = FeedbackActions.GetAction(value);
}
}
}
feedbackAction(text);
}
}
diese Weise können Sie sicher Feedback.ProvideFeedback
nennen können, und sein Verhalten wird von der app/web.config Datei angesteuert werden.
Wenn Sie eine Lösung zu machen brauchen, die fast jede Rückkopplungswirkung zu behandeln flexibel genug ist, würde ich empfehlen, auf inversion of control im Allgemeinen zu lesen und die Managed Extensibility Framework (MEF) im Besonderen. Eine vollständige Umsetzung wäre ein bisschen zu komplex sein, hier zu bieten, aber im Allgemeinen wäre es ein bisschen wie folgt aussehen:
public interface IFeedbackAction
{
void ProvideFeedback(string text);
}
public interface IFeedbackMetadata
{
string Name { get; }
}
[Export(typeof(IFeedbackAction)), ExportMetadata("Name", "Console")]
public interface ConsoleFeedbackAction : IFeedbackAction { ... }
[Export(typeof(IFeedbackAction)), ExportMetadata("Name", "Trace")]
public interface TraceFeedbackAction : IFeedbackAction { ... }
public static class Feedback
{
[ImportMany]
public IEnumerable<Lazy<IFeedbackAction, IFeedbackMetadata>> FeedbackActions { get; set; }
private IFeedbackAction feedbackAction;
public static void ProvideFeedback(string text)
{
if (feedbackAction == null)
{
// synchronize to avoid duplicate calls
lock (syncLock)
{
if (feedbackAction == null)
{
var value = ConfigurationManager.AppSettings["FeedbackAction"];
feedbackAction = GetFeedbackAction(value);
}
}
}
feedbackAction.ProvideFeedback(text);
}
private static IFeedbackAction GetFeedbackAction(string name)
{
return FeedbackActions
.First(l => l.Metadata.Name.Equals(name)).Value;
}
}
Mit dieser Methode die Verbraucher ihre eigene Implementierung von IFeedbackAction
, verziert mit dem zur Verfügung zu stellen wäre in der Lage entsprechende [Export]
und [ExportMetadata]
Attribute, und geben Sie einfach die Verwendung ihrer benutzerdefinierten Aktionen in der Datei app/web.config an.
Nun, erstellen Sie eine Eigenschaft und auf dem Setter überprüfen Sie einfach, ob das Backed-Feld Null ist, wenn es null ist, dann legen Sie es und wenn es nicht Null ist den Wert im Hintergrund zu verwerfen. – Gusman
@Gusman: Tut mir leid, ich habe es gerade aktualisiert. Ich möchte auch nicht, dass es es verschluckt, denn das würde bedeuten, dass jemand diese Einstellung aktualisieren möchte und es einfach nicht getan hat. – user420667
Hmmm, dann kann ich nicht verstehen, was du mit * mein Ziel meinst, in der Lage zu sein, die Feedback-Aktion einmal und nur in einer Art von benutzerdefinierten App-Einstellungen zu spezifizieren, und keine Laufzeitausnahme auf zweite Einstellung zu werfen * – Gusman