class CustomerMessage
{
private string name;
private Dictionary<MethodBase, object> changeTrackingMethods =
new Dictionary<MethodBase, object>();
public int Id {开发者_如何学Python 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
});
}
}
As you can see I am tracking the changes on this incoming message, to run the changes on another object. The method to run is passed to PropertyChanged as a string. Does anyone have a tip how I can make this type safe?
Something like this?
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);
}
}
}
So you want to avoid passing the method name as a string? Why not get the MethodBase object in the 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);
}
Instead of storing the "operation that needs to be done" as a pair of method and an argument that should be passed to it using Reflection, you can store a delegate that should be executed. The simplest way to do this is to store a list of type List<Action<Customer>>
- then in the ApplyChanges
method, you can iterate over the list and run all the actions.
In case you're not using .NET 3.5 and C# 3.0 (which defines a generic delegate Action
and supports lambda expressions), you can still write this 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: It looks like I was slower with writing the code, but I'll keep this here as an explanation - the solution by 'dtb' does exactly what I described.
精彩评论