2010-11-19 90 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