views:

48

answers:

1

I'm playing around with Sqlite and Attributes, and I have properties throughout my code that look like this:

const string FooKey = "foo";

...

string m_foo;
[DatabaseColumn (FooKey)]
public string Foo {
    get { return m_foo; }
    set {
        if (m_foo == value)
            return;

        m_foo = value;
        OnFooChanged (); // Calls the event FooChanged after a null check
        Update (FooKey, Foo); // Updates the field in the database
    }
}

This is identical for each property that corresponds to a column in the table, with the only changes being the name and type. I.e., there might by another property like this:

const string BarKey = "bar";

...

bool m_bar;
[DatabaseColumn (BarKey)]
public bool Bar {
    get { return m_bar; }
    set {
        if (m_bar == value)
            return;

        m_bar = value;
        OnBarChanged (); // Calls the event BarChanged after a null check
        Update (BarKey, Bar); // Updates the field in the database
    }
}

Right now I only use the DatabaseColumn attribute to identify which fields correspond to columns in the table, so that I can more easily insert the whole row into the database. Is there any way to make more of this the responsibility of DatabaseColumn, to reduce boilerplate in my code?

+2  A: 

How about something starting:

private void SetField<T>(
    ref T field, T value,
    string key, EventHandler handler)
{
    if(EqualityComparer<T>.Default
        .Equals(field, value)) return;
    field = value;
    if(handler!=null) handler(this, EventArgs.Empty);
    if(key!=null) Update(key,value);
}
public int Foo {
    get { return foo; }
    set { SetField(ref foo, value, FooKey, FooChanged); }
}

Re re question of using the attributes; that introduces reflection which is comparatively slow. I would a avoid it if possible.

Marc Gravell
@Marc: Thanks, this works great. I've got to get in the habit of using these generic methods.
Matthew