2010-11-19 2 views
2

Ich versuche, ein Datenbankfeld ("LS_RECNUM") mögliche Werte von NULL, "M" und "F" einer Eigenschaft mit einem Gender-Aufzählungstyp zuzuordnen.NHibernate: Get und Set-Methoden von Custom Property Accessor werden nicht aufgerufen

Die Abbildung sieht wie folgt aus:

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

... und die GenderPropertyAccessor Klasse sieht wie folgt aus:

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

nicht besonders vertraut mit Reflexion zu sein, ich bin nicht sicher, dass Die Methoden Get und Set wurden korrekt implementiert.

Wenn ich dies versuche, bekomme ich immer noch eine Fehlermeldung 'Kann nicht als Geschlecht analysieren'. Ich habe versucht, die GenderPropertyAccessor-Klasse zu debuggen. Die entsprechende Zeile (siehe oben) in der Mapping-Datei wird korrekt ausgeführt, genauso wie der Konstruktor für die GenderGetterSetter-Klasse, aber die Methoden Get und Set werden niemals aufgerufen !!!

Kann mir jemand sagen, was ich falsch machen könnte?

Antwort

3

Ich würde eine Implementierung von IUserType dafür verwenden. Hier ist ein good simple example. In den Methoden NullSafeGet und NullSafeSet mutieren Sie die Zeichenfolge zu einer Enum und zurück. Es ist auch wichtig, dass die Equals-Implementierung korrekt ist, damit NHibernate Änderungen erkennt.

die Eigenschaft Zuordnen eines benutzerdefinierten Typs zu verwenden ist einfach:

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

Jamie, diese wandelt das ‚F‘/‚M‘ in das Geschlecht Enum richtig, aber wenn ich auf dem Geschlecht Eigenschaft Abfrage mit Linq Ich bekomme dies: Typ nicht übereinstimmen in NHibernate.Criterion.SimpleExpression: Deceased.Gender erwarteten Typ Kctc.NHibernate.Lawbase.UserTypes.GenderUserType, tatsächlichen Typ Kctc.Gender – David

+0

Sollte dies funktioniert haben? Habe ich es falsch gemacht? – David

+0

Entschuldigung. Ich habe ReturnedType so eingestellt, dass typeof (MyUserType) zurückgegeben wird und nicht typeof (Gender). Das jetzt behoben, und es funktioniert wunderbar! Danke, dass du ein wenig Sternenstaub in meinen Tag gestreut hast. – David