2010-11-19 3 views
2

Je tente de mapper un champ de base de données ("LS_RECNUM") valeurs possibles de NULL, 'M' et 'F' à une propriété avec un type d'énumération de genre.NHibernate: Les méthodes Get et Set de l'accesseur de propriétés personnalisées ne sont pas appelées

La cartographie ressemble à ceci:

Map(x => x.Gender).Column("LS_GENDER").Access.Using<GenderPropertyAccessor>(); 

... et la classe GenderPropertyAccessor ressemble à ceci:

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; } 
    } 
} 

Ne pas être particulièrement familier avec la réflexion, je ne suis pas du tout sûr que les méthodes Get et Set ont été implémentées correctement.

Lorsque j'essaie cela, j'obtiens toujours une erreur 'Impossible d'analyser F en fonction du sexe'. J'ai essayé de déboguer la classe GenderPropertyAccessor. La ligne correspondante (illustrée ci-dessus) dans le fichier de mapping s'exécute correctement, tout comme le constructeur de la classe GenderGetterSetter, mais les méthodes Get et Set ne sont jamais appelées !!! Est-ce que quelqu'un peut me dire ce que je pourrais faire de mal?

Répondre

3

Je voudrais utiliser une implémentation de IUserType pour cela. Voici un good simple example. Dans les méthodes NullSafeGet et NullSafeSet, vous allez muter la chaîne en une énumération et en retour, respectivement. Il est également essentiel que votre implémentation Equals soit correcte pour que NHibernate puisse détecter les changements.

Cartographie de la propriété à utiliser un type d'utilisateur personnalisé est facile:

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

Jamie, ce convertit le « F »/« M » correctement dans le ENUM de genre, mais quand je fais une recherche sur la propriété Sexe LINQ Je reçois ceci: Type incompatibilité dans NHibernate.Criterion.SimpleExpression: Deceased.Gender attendu type Kctc.NHibernate.Lawbase.UserTypes.GenderUserType, type réel Kctc.Gender – David

+0

Si cela a fonctionné? Est-ce que je l'ai fait mal? – David

+0

Mes excuses. Je définis ReturnedType pour renvoyer typeof (MyUserType) plutôt que typeof (Gender). Fixé ceci maintenant, et cela fonctionne magnifiquement! Merci d'avoir saupoudré un peu de poussière d'étoile dans ma journée. – David

Questions connexes