Hugh Hunter

Hacking his way through the weeds, the.dudeabid.es

Using Reflection to Execute Accessors for Property Names Stored in a Variable

| Comments

I had a task to create an export process that would prepare some data to be sent over to an external vendor. The only catch was that I expected a lot of fields in my database to contain data that was longer than the external vendor to accept. I needed to do some simple length validatinos for every field that I was exporting.

From my limited experience using DataAnnotations in my .Net MVC projects, I knew this was the best wy to accomplish this. But how to use DataAnnotations in a non-web application? So the first challenge was to figure out how to run the validations since they’re run automatically in the context of a web request:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using System.ComponentModel.DataAnnotations;

...snip...

[StringLength(35)]
public string Address1 { get; set; } //LEN 35
[StringLength(35)]
public string Address2 { get; set; } //LEN 35

private bool TryValidate(out List<ValidationResult> results)
{
    var context = new ValidationContext(this, serviceProvider: null, items: null);
    results = new List<ValidationResult>();
    return Validator.TryValidateObject(this, context, results, true);
}

Not so bad. But what do you do with this List business?

The next challenge was to try to fix-up the data that failed the length validations. The example below fixes some common verbosity in addresses that was safe to do to try to get them within the 35 character limit.

Then, using reflection, I was able to update the object being exported in a generic way:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
private void Fixup(List<ValidationResult> results)
{
    foreach (ValidationResult result in results)
    {
        \\ the name of the key that failed
        string key = result.MemberNames.First();

        var type = this.GetType();
        var prop = type.GetProperty(key);

        if (Regex.IsMatch(key, "Address"))
        {
            // the value that failed validation
            var val = prop.GetValue(this, null).ToString();

            // do our best to shorten this field for ourselves
            val = val.Replace("Street", "St");
            val = val.Replace("Avenue", "Ave");
            val = val.Replace("Floor", "Fl");
            val = val.Replace("Suite", "Ste");
            val = val.Replace("Drive", "Dr");
            val = val.Replace("Boulevard", "Blvd");
            val = val.Replace("Apartment", "Apt");

            // set the property on the object
            prop.SetValue(this, val, null);
        }
    }

    results.Clear();
    if (!this.TryValidate(out results))
    {
        // log that we failed to fixup a record --- manual intervention required
    }
}

Connecting MySQL Command Line Client to MAMP on OSX

| Comments

I’ve been coming around lately to the local development environment vs doing all of my development on a remote server. The last thing I moved onto my laptop was MySQL and I am used the popular (and free) tool MAMP to get it running quickly.

However, as I am a fan of the MySQL command-line client, I went to test my installation by running:

1
$ mysql -uroot -p

I expected a connection to the server running on localhost. What I got was an error:

1
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)

It turns out that MAMP sets up its unix socket in /Applications/MAMP/tmp/mysql/mysql.sock /tmp/mysql.sock rather than in /tmp/mysql.sock (where the MySQL command line client looks for it. Rather than passing in a messy --socket option to mysql, I opted for the following, which did the trick:

1
$ sudo ln -s /Applications/MAMP/tmp/mysql/mysql.sock /tmp/mysql.sock