【问题标题】:NHibernate: Custom Property Accessor's Get and Set methods not being calledNHibernate:未调用自定义属性访问器的 Get 和 Set 方法
【发布时间】:2010-11-19 10:54:40
【问题描述】:

我正在尝试将数据库字段(“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 方法!!!

谁能告诉我我做错了什么?

【问题讨论】:

    标签: nhibernate fluent-nhibernate nhibernate-mapping


    【解决方案1】:

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

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

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

    【讨论】:

    • Jamie,这会将 'F'/'M' 正确转换为 Gender 枚举,但是当我使用 Linq 查询 Gender 属性时,我得到: NHibernate.Criterion.SimpleExpression 中的类型不匹配:已故.Gender 预期类型 Kctc.NHibernate.Lawbase.UserTypes.GenderUserType,实际类型 Kctc.Gender
    • 我很抱歉。我将 ReturnedType 设置为返回 typeof(MyUserType) 而不是 typeof(Gender)。现在解决了这个问题,它工作得很好!感谢您为我的一天洒下一点星尘。
    • 不客气。从你的化身来看,你可能想暂时放下星尘。或双倍剂量,这是你的电话。 :-) 一定要测试 Equals 的实现,这让我不止一次感到困惑。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-08
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    相关资源
    最近更新 更多