Generate custom setter using attributes
Asked Answered
G

2

7

In classes whose instances I persist using an object database, I keep having to do this:

private string _name;
public string Name
    {
    get { return this._name; }
    set { _name = value; this.Save(); }
    }

whereas I would much rather type this:

[PersistedProperty(Name)]
private string _name;

where the PersistedProperty attributes generates a Getter and Setter just like the default [Property()] attribute, except I want to add a line of code to the generated Setter.

Is there a way I can create an attribute which does this? Hopefully , which works with Intellisense.

How does the default [Property()] attribute even do it's stuff? If I saw the code I could graft that...

Note: I am actually doing this in Boo, but thought I'd give c# code as more people might be willing to answer that, however, if there is a Boo specific solution, I'm all ears!

Update:

My aim was simply to reduce typing and clutter. It turns out the simplest way of doing this was with a script which generates partial classes based on markup in my classes.

Auto-generating source code from markup (in tandem with partial classes) is easy, and actually looks like an extremely promising way to get round some of the problems we normally try to solve with inheritance and generic types.

Goulet answered 8/8, 2012 at 16:21 Comment(4)
Is there a specific reason why you want to do this? or do you just want to save a little bit of time?Secretarial
What is the "default [Property()] attribute"?Dawson
@SamIam it's to save time and reduce clutter.Goulet
I often use Excel or Regex find replace to create Properties for Fields.Germaine
D
1

This requires aspect oriented programming. While not directly supported in .NET, it can be done via third party tooling, such as PostSharp.

For intellisense to work, however, this must be done in a library, as the (final) compiled code will be unrolled into the full property getter/setter.

Dawson answered 8/8, 2012 at 16:27 Comment(1)
Since this post there has been an excellent write-up with example code about AOP in C#. Write-up: dotnetcurry.com/patterns-practices/1305/… Code: github.com/ymassad/AOPExamplesFumble
S
1

Not easy to implement using attributes IMO. Maybe you could use another approach, such as an extension method:

// Extension method that allows updating a property
// and calling .Save() in a single line of code.
public static class ISaveableExtensions
{
    public static void UpdateAndSave<T>(
        this ISaveable instance,
        Expression<Func<T>> propertyExpression, T newValue)
    {
        // Gets the property name
        string propertyName = ((MemberExpression)propertyExpression.Body).Member.Name;

        // Updates its value
        PropertyInfo prop = instance.GetType().GetProperty(propertyName);
        prop.SetValue(instance, newValue, null);

        // Now call Save
        instance.Save();
    }
}
...
// Some interface that implements the Save method
public interface ISaveable
{
    void Save();
}
...
// Test class
public class Foo : ISaveable
{
    public string Property { get; set; }

    public void Save()
    {
        // Some stuff here
        Console.WriteLine("Saving");
    }

    public override string ToString()
    {
        return this.Property;
    }
}
...
public class Program
{
    private static void Main(string[] args)
    {
        Foo d = new Foo();

        // Updates the property with a new value, and automatically call Save
        d.UpdateAndSave(() => d.Property, "newValue");

        Console.WriteLine(d);
        Console.ReadKey();
    }
}

It's type-safe, autocompletion-friendly, but it requires more code than just .Save() in all setters, so not sure I would use it actually...

Slangy answered 8/8, 2012 at 16:48 Comment(1)
This requires me to call a method, whereas I am looking for it to happen in the setter as the instances will be edited in DataGridViews and such.Goulet

© 2022 - 2024 — McMap. All rights reserved.