I ended up implementing a new user type using IUserType. In fact, I found a novel way of minimizing the work needed to implement new user type for immutable types, since only a few of the members need to really be implemented when extending an immutable type such as DateTime. Here's my code:
[Serializable]
public class DateTimeKindLocalType : BaseImmutableUserType<DateTime>
{
public override object NullSafeGet(IDataReader rs, string[] names, object owner)
{
//This is the line that I needed
return DateTime.SpecifyKind((DateTime)NHibernateUtil.DateTime2.NullSafeGet(rs, names), DateTimeKind.Local);
}
public override void NullSafeSet(IDbCommand cmd, object value, int index)
{
NHibernateUtil.DateTime2.NullSafeSet(cmd, value, index);
}
public override SqlType[] SqlTypes
{
get { return new[] {NHibernateUtil.DateTime2.SqlType}; }
}
}
[Serializable]
public class DateTimeKindLocalTypeConvention
: UserTypeConvention<DateTimeKindLocalType>
{
}
[Serializable]
public class DateTimeKindLocalNullableType : BaseImmutableUserType<DateTime?>
{
public override object NullSafeGet(IDataReader rs, string[] names, object owner)
{
if (owner == null)
return null;
return DateTime.SpecifyKind((DateTime)NHibernateUtil.DateTime2.NullSafeGet(rs, names), DateTimeKind.Local);
}
public override void NullSafeSet(IDbCommand cmd, object value, int index)
{
NHibernateUtil.DateTime2.NullSafeSet(cmd, value, index);
}
public override SqlType[] SqlTypes
{
get { return new[] { NHibernateUtil.DateTime2.SqlType }; }
}
}
[Serializable]
public class DateTimeKindLocalNullableTypeConvention
: UserTypeConvention<DateTimeKindLocalNullableType>
{
}
[Serializable]
public abstract class BaseImmutableUserType<T> : IUserType
{
public abstract object NullSafeGet(IDataReader rs, string[] names, object owner);
public abstract void NullSafeSet(IDbCommand cmd, object value, int index);
public abstract SqlType[] SqlTypes { get; }
public new 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.GetHashCode();
}
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 DeepCopy(cached);
}
public object Disassemble(object value)
{
return DeepCopy(value);
}
public Type ReturnedType
{
get { return typeof(T); }
}
public bool IsMutable
{
get { return false; }
}
}
Basically, I have created (copied from somewhere else, sorry forgot source) a base class called BaseImmutableUserType<T> that essentially creates an IUserType based on an immutable type, but allows subclasses to extend the functionality of the NullSafeGet() and NullSafeSet() operations (which are essentially the Get and Set operations and alongwith SqlTypes, that's all I need to override in the subclass). I imagine I'll need to override different types more in the long run, so I decided to use a generalized solution for immutable types. Another point to note is that I had to do this both both DateTime and DateTime?. This is my Fluent configuration:
_fnhConfig = Fluently.Configure().Database(
MsSqlConfiguration.MsSql2008.ConnectionString(ConnectionString)
).Mappings(m => m.FluentMappings.AddFromAssemblyOf<DataAccess.NHMG.Fluent.Mapping.DBBufferMap>()
.Conventions.Add(
DefaultLazy.Never()
,DefaultCascade.None()
===> ,new DateTimeKindLocalTypeConvention()
===> ,new DateTimeKindLocalNullableTypeConvention()
));
Please let me know if there are questions and I'll try to answer as quick as possible.