Base64 Encoded byte[]

Apr 12, 2010 at 5:30 PM
Edited Apr 12, 2010 at 5:34 PM

I would like to store a byte[] as a single Base64 encoded string when Putting to SimpleDB.  I have come up with one viable option that is not so desirable and another that doesn't work as is.  First, the approach I would like to use, that doesn't quite work:


    public class Test

    {
        [ItemName]
        public string Id { get; set; }

        [CustomFormat(typeof(BytesFormatter))]
        [SavantInclude]
        public byte[] Bytes { get; set; }
    }

    public class BytesFormatter : ITypeFormatter
    {
        public string ToString(object value)
        {
            return Convert.ToBase64String((byte[])value);
        }

        public object ToType(string valueString, Type expected)
        {
            return Convert.FromBase64String(valueString);
        }
    }

This doesn't work because the ToString method is called once for each element in the byte[] instead of once for the array.  Understandable, but is there a way to get the behaviour I want?

The less desirable approach is as follows:
    public class Test
    {
        [ItemName]
        public string Id { get; set; }
        public byte[] Bytes 
        {
            get
            {
                return Convert.FromBase64String(BytesString);
            }
            set
            {
                BytesString = Convert.ToBase64String(value);
            } 
        }
        public string BytesString { get; set; }
    }

The byte[] is ignored when Putting and the the encoded string goes in nicely.  Any thoughts on how to better accomplish my goal here?
Coordinator
Apr 12, 2010 at 6:46 PM
Edited Apr 12, 2010 at 8:47 PM

Until now I've specifically not supported arrays since generic lists are better in almost every case when you are actually dealing with multi-valued attributes. But I've been meaning to look at the byte array case (have had a work item open for this for several months), and since you've prompted me I've gone ahead and checked in a change that will cause arrays to be treated as scalar values for formatting purposes. If you're comfortable working with non-release code you can grab the changes and plow ahead with solution #1. Actually, there's a ByteArrayFormatter class included with the check-in so you can even drop your custom formatter (but you will still need the custom format attribute).

Otherwise, the only alternative I can suggest with v0.5 is to wrap your array in another class like this:

public class ByteHolder {
public byte[] Bytes {get; set;}
}

The problem is that Savant v0.5 checks if the propery value is an ICollection to determine if it should be treated as a multi-valued attribute, and arrays do implement that interface.

Also, FYI, you can drop the [SavantInclude] attribute if you're using v0.5 as it's smart enough now to automatically include the property if you attach any Savant attribute.