Rendere questa riflessione chiamata al metodo typesafe
-
01-10-2019 - |
Domanda
class CustomerMessage
{
private string name;
private Dictionary<MethodBase, object> changeTrackingMethods =
new Dictionary<MethodBase, object>();
public int Id { get; set; }
public string Name {
get { return this.name; }
set
{
this.name = value;
this.PropertyChanged("SetName", value);
}
}
private void PropertyChanged(string behaviorMethod, object value)
{
var method = typeof(Customer).GetMethod(behaviorMethod);
this.changeTrackingMethods.Add(method, value);
}
public void ApplyChanges(Customer c)
{
foreach (var changedProperty in this.changeTrackingMethods)
changedProperty.Key.Invoke(c, new object[] {
changedProperty.Value
});
}
}
Come potete vedere sto tracking dei cambiamenti su questo messaggio in arrivo, per eseguire le modifiche su un altro oggetto. Il metodo di esecuzione viene passato a PropertyChanged come stringa. Qualcuno ha un suggerimento come posso fare questo tipo di sicurezza?
Soluzione
Una cosa come questa?
class CustomerMessage
{
private string name;
private List<Action<Customer>> changeTrackingMethods =
new List<Action<Customer>>();
public int Id { get; set; }
public string Name {
get { return this.name; }
set
{
this.name = value;
this.changeTrackingMethods.Add(c => { c.SetName(value) });
}
}
public void ApplyChanges(Customer c)
{
foreach (var action in this.changeTrackingMethods)
{
action(c);
}
}
}
Altri suggerimenti
Così si vuole evitare di passare il nome del metodo come una stringa? Perché non avere l'oggetto MethodBase nel setter?
public string Name {
get { return this.name; }
set
{
this.name = value;
this.PropertyChanged(typeof(Customer).GetMethod(behaviorMethod), value);
}
}
private void PropertyChanged(MethodBase method, object value)
{
this.changeTrackingMethods.Add(method, value);
}
Invece di memorizzare la "operazione che deve essere fatto" come una coppia di metodo ed un argomento che deve essere passato ad esso utilizzando Reflection, è possibile memorizzare un delegato che deve essere eseguito. Il modo più semplice per farlo è quello di memorizzare un elenco di tipo List<Action<Customer>>
- poi nel metodo ApplyChanges
, è possibile iterare l'elenco ed eseguire tutte le azioni.
Nel caso in cui non si sta utilizzando .NET 3.5 e C # 3.0 (che definisce un generico delegato Action
e supporta le espressioni lambda), è comunque possibile scrivere questo in C # 2.0:
// you can define a delegate like this
delegate void UpdateCustomer(Customer c);
// and you could use anonymous methods
// (instead of more recent lambda expressions)
list.Add(delegate (Customer c) { c.SetName("test"); });
EDIT:. Sembra che io ero più lento con la scrittura del codice, ma mi terrò questo qui come una spiegazione - la soluzione da 'DTB' è esattamente quello che ho descritto