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

NHibernate:自定义属性访问器';s Get和Set方法未被调用,nhibernate,fluent-nhibernate,nhibernate-mapping,Nhibernate,Fluent Nhibernate,Nhibernate Mapping,我正在尝试将一个可能为NULL、'm'和'F'的数据库字段(“LS_RECNUM”)值映射到一个具有性别枚举类型的属性 映射如下所示: Map(x => x.Gender).Column("LS_GENDER").Access.Using<GenderPropertyAccessor>(); using System; using System.Collections; using System.Reflection; using Kctc; using NHibernate

我正在尝试将一个可能为NULL、'm'和'F'的数据库字段(“LS_RECNUM”)值映射到一个具有性别枚举类型的属性

映射如下所示:

Map(x => x.Gender).Column("LS_GENDER").Access.Using<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; }
  }
}
Map(x=>x.Gender).Column(“LS_Gender”).Access.Using();
…而GenderPropertyAccessor类如下所示:

Map(x => x.Gender).Column("LS_GENDER").Access.Using<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; }
  }
}
使用系统;
使用系统集合;
运用系统反思;
使用Kctc;
使用NHibernate.发动机;
使用NHibernate。性质;
公共类GenderPropertyAccessor:IPropertyAccessor
{
#区域设定器
私有类GenderGetterSetter:IGetter,ISetter
{
不动产信息不动产;
公共GenderGetterSetter(属性信息属性)
{
如果(property==null)抛出新的ArgumentNullException(“property”);
如果(property.PropertyType!=typeof(Gender))抛出新的ArgumentException(“属性”);
_财产=财产;
}
public void Set(对象目标,对象值)//将字符串转换为枚举
{
_SetValue(目标,GetGenderFromString(值),null);
}
public object Get(object target)//将枚举转换回字符串
{
性别=(性别)_property.GetValue(目标,空);
返回设置GenderTostring(性别);
}
/// 
///将提供的字符串解释为性别。
/// 
///性别为“F”或“M”。
/// 
私有性别GetGenderFromString(对象字符串)
{
if(strGender==null)返回Gender.Unknown;
开关(strGender.ToString().ToLower())
{
案例“f”:
返回性别。女性;
案例“m”:
返回性别:男性;
违约:
返回性别。未知;
}
}
/// 
///将提供的性别设置为适当的“M”或“F”值。
/// 
///性别。
/// 
私有字符串SetGenderToString(对象对象objGender)
{
性别=(性别)objGender;
开关(性别)
{
案件性别:女性:
返回“F”;
案件性别:男:
返回“M”;
违约:
返回null;
}
}
公共方法信息方法
{
获取{return null;}
}
公共字符串PropertyName
{
获取{return\u property.Name;}
}
公共对象GetForInsert(对象所有者、IDictionary合并映射、ISessionImplementor会话)
{
返回获取(所有者);
}
公共类型返回类型
{
获取{return typeof(byte[]);}
}
}
#端区
公共IGetter getter(键入类、字符串属性名称)
{
返回新的GenderGetterSetter(class.GetProperty(propertyName));
}
公共ISetter GetSetter(键入类、字符串属性名称)
{
返回新的GenderGetterSetter(class.GetProperty(propertyName));
}
公共bool可以通过reflectionOptimizer访问
{
获取{return false;}
}
}
由于不太熟悉反射,我根本不确定Get和Set方法是否正确实现

当我尝试此操作时,仍然会出现一个错误“无法将F解析为性别”。我试过调试GenderPropertyAccessor类。映射文件中的相关行(如上所示)正在正确执行,GenderGetterSetter类的构造函数也在正确执行,但从未调用Get和Set方法


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

我会为此使用IUserType的实现。这是一个例子。在NullSafeGet和NullSafeSet方法中,您将分别将字符串变异为枚举和返回。为了使NHibernate能够检测到更改,Equals实现是否正确也是至关重要的

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

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

Jamie,这会正确地将'F'/'M'转换为性别枚举,但是当我使用Linq查询性别属性时,我得到以下结果:NHibernate.criteria.SimpleExpression:deased.Gender预期类型Kctc.NHibernate.Lawbase.UserTypes.GenderUserType,实际类型Kctc.GenderMy抱歉。我将ReturnedType设置为returntypeof(MyUserType),而不是typeof(Gender)。现在修复了这个,它工作得很好!谢谢你在我的日子里洒了点星尘。不客气。从你的头像判断,你可能想暂时抛开星尘。或者双倍剂量,由你决定。:-)一定要测试Equals实现,这让我不止一次绊倒。