如何使用不可变类型(如System.Tuple)的NHibernate? [英] How can I use NHibernate with immutable type like System.Tuple?

查看:68
本文介绍了如何使用不可变类型(如System.Tuple)的NHibernate?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用 System.Tuple<int,string> 的复合映射如下:

I have a composite mapping using System.Tuple<int,string> that looks as follows:

<composite-element
  class="System.Tuple`2[[System.Int32, mscorlib],[System.String, mscorlib]], mscorlib">
    <property name="Item1" column="DBColumn1"/>
    <property name="Item2" column="DBColumn2"/>
</composite-element>

我尝试弄乱BytecodeProviderIObjectsFactoryReflectionOptimizer之类的东西,但是我无法让NHibernate正确地加载我的元组(无论做什么,NHibernate坚持首先创建对象并填充值)以后再出来.)

I try messing around with BytecodeProvider, IObjectsFactory, ReflectionOptimizer and whatnot, but I can't get NHibernate to load my Tuple properly (whatever I do, NHibernate insists on creating the object first and filling the values out later).

可以以某种方式强制NHibernate正确加载和保留不可变类型吗?

Can NHibernate be somehow coerced to properly load and persist immutable types?

推荐答案

您是否尝试过 ICompositeUserType ?它将允许您为Tuple<int, string>属性定义映射,如下所示:

Have you tried with ICompositeUserType? It will allow you to define your mappings like this for your Tuple<int, string> property:

<property name="MyProperty" type="MyNamespace.TupleIntStringType, MyAssembly">
    <column name="Item1"/>
    <column name="Item2"/>
</property>

自定义类型定义为:

public class TupleIntStringType : ICompositeUserType
{
    public object GetPropertyValue(object component, int property)
    {
        var tuple = (Tuple<int, string>)component;
        switch (property)
        {
            case 0:
                return tuple.Item1;
            case 1:
                return tuple.Item2;
            default:
                throw new InvalidOperationException(String.Format("No property number {0} found", property));
        }
    }

    public void SetPropertyValue(object component, int property, object value)
    {
        throw new InvalidOperationException("Immutable, SetPropertyValue is not allowed");
    }

    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 == null ? 0 : x.GetHashCode();
    }

    public object NullSafeGet(IDataReader dr, string[] names, ISessionImplementor session, object owner)
    {
        var item1 = (int)PropertyTypes[0].NullSafeGet(dr, names[0], session, owner);
        var item2 = (String)PropertyTypes[1].NullSafeGet(dr, names[1], session, owner);

        return Tuple.Create(item1, item2);
    }

    public void NullSafeSet(IDbCommand cmd, object value, int index, bool[] settable, ISessionImplementor session)
    {
        if (value == null)
        {
            NHibernateUtil.Timestamp.NullSafeSet(cmd, null, index);
            NHibernateUtil.TimeSpan.NullSafeSet(cmd, null, index + 1);
        }
        else
        {
            var tuple = (Tuple<int, String>)value;

            PropertyTypes[0].NullSafeSet(cmd, tuple.Item1, index, session);
            PropertyTypes[1].NullSafeSet(cmd, tuple.Item2, index + 1, session);
        }
    }

    public object DeepCopy(object value)
    {
        var tuple = (Tuple<int, String>)value;
        return Tuple.Create(tuple.Item1, tuple.Item2);
    }

    public object Disassemble(object value, ISessionImplementor session)
    {
        return DeepCopy(value);
    }

    public object Assemble(object cached, ISessionImplementor session, object owner)
    {
        return DeepCopy(cached);
    }

    public object Replace(object original, object target, ISessionImplementor session, object owner)
    {
        return DeepCopy(original);
    }

    public string[] PropertyNames { get { return new[] { "Item1", "Item2" }; } }
    public IType[] PropertyTypes { get { return new IType[] { NHibernateUtil.Int32, NHibernateUtil.String }; } }
    public Type ReturnedClass { get { return typeof(Tuple<int, string>); } }
    public bool IsMutable { get { return false; } }
}

以下是一些示例:
金钱对象和NHibernate ICompositeUserType
使用NHibernate的ICompositeUserType映射时间戳数据/a>
使用具有值类型的NHibernate ICompositeUserType

Here are few examples:
Money object and NHibernate ICompositeUserType
Mapping Timestamp data using NHibernate's ICompositeUserType
Using NHibernate ICompositeUserType with a value type

您的<composite-element>映射然后更改为(如 NHIbernate:如何使用ICompositeUserType映射包 ):

Your mapping of <composite-element> then changes to (as show in NHIbernate: How to map a bag with an ICompositeUserType ):

<element type="MyNamespace.TupleIntStringType, MyAssembly">
  <column name="DBColumn1" />
  <column name="DBColumn2" />
</element>

这篇关于如何使用不可变类型(如System.Tuple)的NHibernate?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆