映射System.Drawing.Color

时间:2012-10-01 19:59:03

标签: c# fluent-nhibernate

如果我没有映射Color但映射具有Color属性的对象,则FluentNHibernate会成功将其映射到varbinary(max)。然而,鉴于实际上Color只由4个字节组成,而且我很想改进它而不使用新类型来代理它,这是非常低效的。

Color内,它由四个属性组成,

  1. long value(向下转换为int代表ARGB)
  2. short state,表示这是否已知&有效颜色
  3. string name,颜色的名称(如果已知)。
  4. short knownColor一个值,表示它是哪种已知颜色
  5. 所以我试图将其映射如下。

    public ColorMapping()
    {
        CompositeId()
            .KeyProperty(c => Reveal.Member<Color, long>("value"))
            .KeyProperty(c => Reveal.Member<Color, short>("state"))
            .KeyProperty(c => Reveal.Member<Color, string>("name"))
            .KeyProperty(c => Reveal.Member<Color, short>("knownColor"));
    }
    

    然而,在使用时我得到以下异常,

      

    类初始化方法DataContextTest.ClassInitialise抛出   例外。 FluentNHibernate.Cfg.FluentConfigurationException:   FluentNHibernate.Cfg.FluentConfigurationException:无效或   创建SessionFactory时使用了不完整的配置。   检查PotentialReasons集合,以及InnerException以获取更多详细信息。

         

    ---&GT; FluentNHibernate.Cfg.FluentConfigurationException:无效或   创建SessionFactory时使用了不完整的配置。   检查PotentialReasons集合,以及InnerException以获取更多详细信息。

         

    ---&GT; NHibernate.MappingException:无法编译映射   文件:(XmlDocument)---&gt; NHibernate.MappingException:不能   确定类型:   System.Linq.Expressions.Expression 1[[System.Func -2 - [[的System.Drawing.Color,   System.Drawing,Version = 4.0.0.0,Culture = neutral,   PublicKeyToken = b03f5f7f11d50a3a],[System.Int64,mscorlib,   Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089]],   mscorlib,版本= 4.0.0.0,文化=中性,   PublicKeyToken = b77a5c561934e089]],System.Core,Version = 4.0.0.0,   Culture = neutral,PublicKeyToken = b77a5c561934e089,列:   NHibernate.Mapping.Column(会员)。

    我是否误用Reveal?如果是这样,我打算如何使用它?

2 个答案:

答案 0 :(得分:1)

我会将其映射为UserType,来回转换它

// in mapping
Map(x => x.Color).Column("ColorARGB").CustomType<ColorUserType>();

[Serializable]
class ColorUserType : IUserType
{
    public object Assemble(object cached, object owner)
    {
        return DeepCopy(cached);
    }

    public object DeepCopy(object value)
    {
        return value;
    }

    public object Disassemble(object value)
    {
        return DeepCopy(value);
    }

    bool IUserType.Equals(object x, object y)
    {
        var colorX = x as Color;
        var colorY = y as Color;
        return colorX == null ? colorY = null : colorX.ToArgb() == colorY.ToArgb();
    }

    public virtual int GetHashCode(object x)
    {
        var colorX = (Color)x;
        return (colorX != null) ? colorX.ToArgb() : 0;
    }

    public bool IsMutable { get { return false; } }

    public object NullSafeGet(IDataReader rs, string[] names, object owner)
    {
        return Color.FromArgb((int)NHibernateUtil.Int32.Get(rs, names[0]));
    }

    public void NullSafeSet(IDbCommand cmd, object value, int index)
    {
        NHibernateUtil.Int32.Set(cmd, ((Color)value).ToArgb(), index);
    }

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

    public Type ReturnedType { get { return typeof(Color); } }

    public SqlType[] SqlTypes { get { return new []{ SqlTypeFactory.Int32 }; } }
}

答案 1 :(得分:0)

我最后使用了ICompositeUserType。 代码如下,

public class ColorType : ICompositeUserType
{
    /// <summary>
    /// Get the value of a property
    /// </summary>
    /// <param name="component">an instance of class mapped by this "type"</param>
    /// <param name="property"/>
    /// <returns>
    /// the property value
    /// </returns>
    public object GetPropertyValue(object component, int property)
    {
        var color = (Color) component;
        if (property == 0)
        {
            return color.ToArgb();
        }

        return (int) color.ToKnownColor();
    }

    /// <summary>
    /// Set the value of a property
    /// </summary>
    /// <param name="component">an instance of class mapped by this "type"</param>
    /// <param name="property"/>
    /// <param name="value">the value to set</param>
    public void SetPropertyValue(object component, int property, object value)
    {
        throw new InvalidOperationException("Color is immutable");
    }

    /// <summary>
    /// Compare two instances of the class mapped by this type for persistence
    ///             "equality", ie. equality of persistent state.
    /// </summary>
    /// <param name="x"/><param name="y"/>
    /// <returns/>
    public new bool Equals(object x, object y)
    {
        return ReferenceEquals(x, y) ||
               x != null && y != null &&
               object.Equals(x, y);
    }

    /// <summary>
    /// Get a hashcode for the instance, consistent with persistence "equality"
    /// </summary>
    public int GetHashCode(object x)
    {
        return x == null
                   ? 0
                   : x.GetHashCode();
    }

    /// <summary>
    /// Retrieve an instance of the mapped class from a IDataReader. Implementors
    ///             should handle possibility of null values.
    /// </summary>
    /// <param name="dr">IDataReader</param>
    /// <param name="names">the column names</param>
    /// <param name="session"/>
    /// <param name="owner">the containing entity</param>
    /// <returns/>
    public object NullSafeGet(IDataReader dr, string[] names,
        ISessionImplementor session, object owner)
    {
        var argb = (int?) NHibernateUtil.Int32.NullSafeGet(dr, names[0]);
        var knownColor = (int?) NHibernateUtil.Int32.NullSafeGet(dr, names[1]);
        return knownColor != null
            ? Color.FromKnownColor((KnownColor) knownColor.Value)
            : Color.FromArgb(argb.Value);
    }

    /// <summary>
    /// Write an instance of the mapped class to a prepared statement.
    ///             Implementors should handle possibility of null values.
    ///             A multi-column type should be written to parameters starting from index.
    ///             If a property is not settable, skip it and don't increment the index.
    /// </summary>
    /// <param name="cmd"/>
    /// <param name="value"/>
    /// <param name="index"/>
    /// <param name="settable"/>
    /// <param name="session"/>
    public void NullSafeSet(IDbCommand cmd, object value, int index,
        bool[] settable, ISessionImplementor session)
    {
        var color = (Color) value;
        if (color.IsKnownColor)
        {
            ((IDataParameter) cmd.Parameters[index]).Value = DBNull.Value;
            ((IDataParameter) cmd.Parameters[index + 1]).Value = (int) color.ToKnownColor();
        }
        else
        {
            ((IDataParameter) cmd.Parameters[index]).Value = color.ToArgb();
            ((IDataParameter) cmd.Parameters[index + 1]).Value = DBNull.Value;
        }
    }

    /// <summary>
    /// Return a deep copy of the persistent state, stopping at entities and at collections.
    /// </summary>
    /// <param name="value">generally a collection element or entity field</param>
    /// <returns/>
    public object DeepCopy(object value)
    {
        return value;
    }

    /// <summary>
    /// Transform the object into its cacheable representation.
    ///             At the very least this method should perform a deep copy.
    ///             That may not be enough for some implementations, 
    ///             method should perform a deep copy. That may not be enough for 
    ///             some implementations, however; for example, associations must 
    ///             be cached as identifier values. (optional operation)
    /// </summary>
    /// <param name="value">the object to be cached</param>
    /// <param name="session"/>
    /// <returns/>
    public object Disassemble(object value, ISessionImplementor session)
    {
        return value;
    }

    /// <summary>
    /// Reconstruct an object from the cacheable representation.
    ///             At the very least this method should perform a deep copy. (optional operation)
    /// </summary>
    /// <param name="cached">the object to be cached</param>
    /// <param name="session"/>
    /// <param name="owner"/>
    /// <returns/>
    public object Assemble(object cached, ISessionImplementor session, object owner)
    {
        return cached;
    }

    /// <summary>
    /// During merge, replace the existing (target) value in the entity we are merging to
    ///             with a new (original) value from the detached entity we are merging. For immutable
    ///             objects, or null values, it is safe to simply return the first parameter. For
    ///             mutable objects, it is safe to return a copy of the first parameter. However, since
    ///             composite user types often define component values, it might make sense to recursively
    ///             replace component values in the target object.
    /// </summary>
    public object Replace(object original, object target, ISessionImplementor session, object owner)
    {
        return original;
    }

    /// <summary>
    /// Get the "property names" that may be used in a query.
    /// </summary>
    public string[] PropertyNames { get { return new[] {"Argb", "KnownColor"}; } }

    /// <summary>
    /// Get the corresponding "property types"
    /// </summary>
    public IType[] PropertyTypes
    {
        get
        {
            return new IType[]
                   {
                       NHibernateUtil.Int32, NHibernateUtil.Int32
                   };
        }
    }

    /// <summary>
    /// The class returned by NullSafeGet().
    /// </summary>
    public Type ReturnedClass { get { return typeof (Color); } }

    /// <summary>
    /// Are objects of this type mutable?
    /// </summary>
    public bool IsMutable { get { return false; } }
}