views:

43

answers:

3
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 
            });
    }
}

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?

+1  A: 

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);
        }
    }
}
dtb
Yes! Thanks alot :)
moe
+1  A: 

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.

Tomas Petricek
I like this solution :-)
dtb
A: 

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);
}
Grzenio