2010-11-19 89 views
2

我试图将一个数据库字段(“LS_RECNUM”)NULL,'M'和'F'的可能值映射到具有Gender枚举类型的属性。NHibernate:自定义属性访问器的Get和Set方法不被调用

的映射是这样的:

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方法永远不会被调用!

有谁能告诉我我可能会做错什么吗?

回答

3

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

映射使用定制的用户类型的属性很容易:

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

杰米,这个正确换算“F” /“M”进入性别枚举,但是当我在使用LINQ性别属性查询我得到这个:类型不匹配在NHibernate.Criterion.SimpleExpression:Deceased.Gender预期类型Kctc.NHibernate.Lawbase.UserTypes.GenderUserType,实际类型Kctc.Gender – David 2010-11-19 13:14:47

+0

这应该工作?我做错了吗? – David 2010-11-19 13:15:20

+0

我的歉意。我将ReturnedType设置为返回typeof(MyUserType)而不是typeof(Gender)。现在修正了这个问题,它的效果非常好!感谢你为我的一天洒上一点点星尘。 – David 2010-11-19 13:20:18