我离得那么远,却又那么近。当然,我们可以在NullSafeGet方法中从IDataReader访问dependent属性。
完整的(-ish)解决方案如下:
首先让我们定义一个流畅的映射:
public class AMap : ClassMap<A>
{
public AMap()
{
Id(x => x.Id);
Map(x => x.SomeString);
Map(x => x.SpecialProperty)
.CustomType(typeof (DependentProperty))
;
}
static object DeserialiseSpecialProperty(string SomeString, byte[] specialProperty)
{
// ...
}
static byte[] SerialiseSpecialProperty(object specialProperty)
{
// ...
}
}
public class DependentProperty: IUserType
{
// change SqlTypes appropriatelly if your backing field is something else
public SqlType[] SqlTypes { get { return new[] {new SqlType(DbType.Binary)}; } }
public Type ReturnedType { get { return typeof (object); } }
public bool IsMutable { get { return false; } }
public int GetHashCode(object x)
{
if (x == null)
return 0;
return x.GetHashCode();
}
public object NullSafeGet(IDataReader rs, string[] names, object owner)
{
var SomeString = (string)rs.GetValue(1);
object obj = NHibernateUtil.Binary.NullSafeGet(rs, names[0]);
return AMap.DeserialiseSpecialProperty(SomeString, (byte[])obj);
}
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 = AMap.DeserialiseSpecialProperty(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; }
bool IUserType.Equals(object x, object y) { return object.Equals(x, y); }
}
笔记:
-
IUserType实现基于
a nhibernate.info tutorial
-
由于直接访问IDataReader,这是
非常易碎
. 对AMap中映射顺序的更改很可能需要更新访问的索引。很可能对AMap的其他更改(甚至可能是A)也会破坏这个实现。
这是令人不快的,是的,但是必须直接在业务对象中存储持久性字段(和自定义序列化程序/反序列化程序包),并在每次获取/设置外部属性时调用这些字段。我认为,持久性验证应取用损坏的索引,并且此实现应导致一般来说,业务/持久性关注点的分离更为清晰。
-
把这个和(拉皮条客我的帖子?)
sqlite's manifest typing capabilities
你还可以做一些非常酷的动态输入功能:)