Is it possible to just do some sort of type conversion and map directly to System.Drawing.Color? I'm storing the colors as html/css values. i.e. #ffffff. I don't want to have to create a custom type that implements IUserType, that is just a wrapper for System.Drawing.Color.
I would do it like this:
I would create a private string property or field in my class, and map this property/field to the column that you use to store the color in your database.
Then, I would create a public property in my class, that returns a Color, and in the getter of that property, I would convert the string that is stored in the private field/property to a Color, and in the setter, I would set the string field/property to the value that corresponds with the Color value that has been given.
public class MyEntity
{
private string htmlColorString;
public Color TheColor
{
get { return System.Drawing.ColorTranslator.FromHtml (htmlColorString); }
set
{
htmlColorString = System.Drawing.ColorTranslator.ToHtml(value);
}
}
}
I would go with Frederik's implementation approach and do the conversion as follows:
Convert hex to RGB -- each pair of hex values is one of the RGB components -- #23FF00 means R=23, G=FF, B=00.
This will give you the int value for each of the RGB components, after you do some string parsing on your hex value:
int.Parse("FF", System.Globalization.NumberStyles.AllowHexSpecifier);
After that, simply call Color.FromArgb() static and you'll have your Color.
I would take the 15 minutes to write an IUserType implementation to convert directly to/from the color property so you don't have any magic properties laying around.
This also has the benefit that you can use your color property in HQL or Linq, which you would not be able to do with magic properties, although with a color this may not be an issue.
Try this for size. An NHibernate user type doesn't replace the type you want to expose, it simply provides the mechanism for automatically mapping from the stored database type to the .NET type (here, from string to Color and vice versa).
public class ColorUserType : IUserType
{
public bool Equals(object x, object y)
{
if (ReferenceEquals(x, y)) return true;
if (x == null || y == null) return false;
return x.Equals(y);
}
public int GetHashCode(object x)
{
return x == null ? typeof(Color).GetHashCode() + 473 : x.GetHashCode();
}
public object NullSafeGet(IDataReader rs, string[] names, object owner)
{
var obj = NHibernateUtil.String.NullSafeGet(rs, names[0]);
if (obj == null) return null;
var colorString = (string)obj;
return ColorTranslator.FromHtml(colorString);
}
public void NullSafeSet(IDbCommand cmd, object value, int index)
{
if (value == null)
{
((IDataParameter)cmd.Parameters[index]).Value = DBNull.Value;
}
else
{
((IDataParameter)cmd.Parameters[index]).Value = ColorTranslator.ToHtml((Color)value);
}
}
public object DeepCopy(object value)
{
return value;
}
public object Replace(object original, object target, object owner)
{
return original;
}
public object Assemble(object cached, object owner)
{
return cached;
}
public object Disassemble(object value)
{
return value;
}
public SqlType[] SqlTypes
{
get { return new[] {new SqlType(DbType.StringFixedLength)}; }
}
public Type ReturnedType
{
get { return typeof(Color); }
}
public bool IsMutable
{
get { return true; }
}
}
The following mapping should then work:
<property
name="Color"
column="hex_color"
type="YourNamespace.ColorUserType, YourAssembly" />
For completeness, and thanks to Josh for this, if you're using FluentNHibernate, you can map it like this:
Map(m => m.Color).CustomTypeIs<ColorUserType>();