代码之家  ›  专栏  ›  技术社区  ›  David

nhibernate:未调用自定义属性访问器的get和set方法

  •  2
  • David  · 技术社区  · 14 年前

    我正在尝试将数据库字段(“ls_recnum”)可能的空值、“m”和“f”映射到具有性别枚举类型的属性。

    映射如下:

    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解析为gender”。我试过调试genderpropertyaccessor类。映射文件中的相关行(如上图所示)正在正确执行,就像gendergettersetter类的构造函数一样,但从未调用get和set方法!!!!

    有人能告诉我我可能做错了什么吗?

    1 回复  |  直到 14 年前
        1
  •  3
  •   Jamie Ide    14 年前

    我将为此使用iusertype的实现。这是一个 good simple example . 在nullsafeget和nullsafeet方法中,您将分别将字符串转换为枚举和返回。同样重要的是,为了让NHibernate检测到变化,您的equals实现是正确的。

    映射属性以使用自定义用户类型很容易:

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