NHibernate: методы Get и Set средства доступа к настраиваемым свойствам не вызываются

Я пытаюсь сопоставить возможные значения NULL, M и F поля базы данных (LS_RECNUM) со свойством с типом перечисления 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 никогда не вызываются !!!

Может ли кто-нибудь сказать мне, что я делаю не так?


person David    schedule 19.11.2010    source источник


Ответы (1)


Я бы использовал для этого реализацию IUserType. Вот хороший простой пример. В методах NullSafeGet и NullSafeSet вы преобразуете строку в перечисление и обратно соответственно. Также важно, чтобы ваша реализация Equals была правильной, чтобы NHibernate мог обнаруживать изменения.

Сопоставить свойство для использования настраиваемого типа пользователя очень просто:

Map(x => x.Gender).Column("LS_GENDER").CustomType(typeof(MyUserType));
person Jamie Ide    schedule 19.11.2010
comment
Джейми, это правильно преобразует 'F' / 'M' в перечисление Gender, но когда я запрашиваю свойство Gender с помощью Linq, я получаю следующее: Несоответствие типа в NHibernate.Criterion.SimpleExpression: Deceased.Gender ожидаемый тип Kctc.NHibernate. Lawbase.UserTypes.GenderUserType, фактический тип Kctc.Gender - person David; 19.11.2010
comment
Мои извенения. Я установил ReturnedType для возврата typeof (MyUserType), а не typeof (Gender). Исправлено это сейчас, и это прекрасно работает! Спасибо, что посыпали мой день немного звездной пылью. - person David; 19.11.2010
comment
Пожалуйста. Судя по вашему аватару, вы можете на время отложить звездную пыль. Или удвойте дозу, ваше дело. :-) Обязательно протестируйте реализацию Equals, это меня не раз сбивало с толку. - person Jamie Ide; 19.11.2010