NHibernate:自定义属性访问器的Get和Set方法未被调用

时间:2010-11-19 10:54:41

标签: nhibernate fluent-nhibernate nhibernate-mapping

我正在尝试将数据库字段(“LS_RECNUM”)的可能值NULL,'M'和'F'映射到具有Gender枚举类型的属性。

映射如下所示:

Map(x => x.Gender).Column("LS_GENDER").Access.Using<GenderPropertyAccessor>();

...且GenderPropertyAccessor类看起来像这样:

using System;
using System.Collections;
using System.Reflection;
using Kctc;
using NHibernate.Engine;
using NHibernate.Properties;

public class GenderPropertyAccessor : IPropertyAccessor
{
  #region Setter

  private class GenderGetterSetter : IGetter, ISetter
  {
    PropertyInfo _property;
    public GenderGetterSetter(PropertyInfo property)
    {
      if (property == null) throw new ArgumentNullException("property");
      if (property.PropertyType != typeof(Gender)) throw new ArgumentException("property");
      _property = property;
    }

    public void Set(object target, object value) //Convert string to enum
    {
      _property.SetValue(target, GetGenderFromString(value), null);
    }

    public object Get(object target) //Convert enum back to string
    {
      Gender gender = (Gender)_property.GetValue(target, null);
      return SetGenderToString(gender);
    }

    /// <summary>
    /// Interprets the supplied string as a gender.
    /// </summary>
    /// <param name="strGender">The gender as either 'F' or 'M'.</param>
    /// <returns></returns>
    private Gender GetGenderFromString(object strGender)
    {
      if (strGender == null) return Gender.Unknown;
      switch (strGender.ToString().ToLower())
      {
        case "f":
          return Gender.Female;
        case "m":
          return Gender.Male;
        default:
          return Gender.Unknown;
      }
    }

    /// <summary>
    /// Sets the supplied Gender to the appropriate 'M' or 'F' value.
    /// </summary>
    /// <param name="objGender">The gender.</param>
    /// <returns></returns>
    private string SetGenderToString(object objGender)
    {
      Gender gender = (Gender) objGender;
      switch (gender)
      {
        case Gender.Female:
          return "F";
        case Gender.Male:
          return "M";
        default:
          return null;
      }
    }

    public MethodInfo Method
    {
      get { return null; }
    }

    public string PropertyName
    {
      get { return _property.Name; }
    }

    public object GetForInsert(object owner, IDictionary mergeMap, ISessionImplementor session)
    {
      return Get(owner);
    }

    public Type ReturnType
    {
      get { return typeof(byte[]); }
    }
  }

  #endregion

  public IGetter GetGetter(Type theClass, string propertyName)
  {
    return new GenderGetterSetter(theClass.GetProperty(propertyName));
  }

  public ISetter GetSetter(Type theClass, string propertyName)
  {
    return new GenderGetterSetter(theClass.GetProperty(propertyName));
  }

  public bool CanAccessThroughReflectionOptimizer
  {
    get { return false; }
  }
}

对反射不是特别熟悉,我完全不确定Get和Set方法是否已正确实现。

当我尝试这个时,我仍然会收到错误“无法将F解析为性别”。我已经尝试调试GenderPropertyAccessor类。映射文件中的相关行(如上所示)正确执行,GenderGetterSetter类的构造函数也是如此,但Get和Set方法永远不会被调用!!!

谁能告诉我自己可能做错了什么?

1 个答案:

答案 0 :(得分:3)

我会为此使用IUserType的实现。这是一个good simple example。在NullSafeGet和NullSafeSet方法中,您将分别将字符串变为枚举和返回。为了让NHibernate检测到变化,你的Equals实现是正确的也是至关重要的。

将属性映射为使用自定义用户类型非常简单:

Map(x => x.Gender).Column("LS_GENDER").CustomType(typeof(MyUserType));