NHibernate:自定义属性访问器';s Get和Set方法未被调用
我正在尝试将一个可能为NULL、'm'和'F'的数据库字段(“LS_RECNUM”)值映射到一个具有性别枚举类型的属性 映射如下所示:NHibernate:自定义属性访问器';s Get和Set方法未被调用,nhibernate,fluent-nhibernate,nhibernate-mapping,Nhibernate,Fluent Nhibernate,Nhibernate Mapping,我正在尝试将一个可能为NULL、'm'和'F'的数据库字段(“LS_RECNUM”)值映射到一个具有性别枚举类型的属性 映射如下所示: Map(x => x.Gender).Column("LS_GENDER").Access.Using<GenderPropertyAccessor>(); using System; using System.Collections; using System.Reflection; using Kctc; using NHibernate
Map(x => x.Gender).Column("LS_GENDER").Access.Using<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; }
}
}
Map(x=>x.Gender).Column(“LS_Gender”).Access.Using();
…而GenderPropertyAccessor类如下所示:
Map(x => x.Gender).Column("LS_GENDER").Access.Using<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; }
}
}
使用系统;
使用系统集合;
运用系统反思;
使用Kctc;
使用NHibernate.发动机;
使用NHibernate。性质;
公共类GenderPropertyAccessor:IPropertyAccessor
{
#区域设定器
私有类GenderGetterSetter:IGetter,ISetter
{
不动产信息不动产;
公共GenderGetterSetter(属性信息属性)
{
如果(property==null)抛出新的ArgumentNullException(“property”);
如果(property.PropertyType!=typeof(Gender))抛出新的ArgumentException(“属性”);
_财产=财产;
}
public void Set(对象目标,对象值)//将字符串转换为枚举
{
_SetValue(目标,GetGenderFromString(值),null);
}
public object Get(object target)//将枚举转换回字符串
{
性别=(性别)_property.GetValue(目标,空);
返回设置GenderTostring(性别);
}
///
///将提供的字符串解释为性别。
///
///性别为“F”或“M”。
///
私有性别GetGenderFromString(对象字符串)
{
if(strGender==null)返回Gender.Unknown;
开关(strGender.ToString().ToLower())
{
案例“f”:
返回性别。女性;
案例“m”:
返回性别:男性;
违约:
返回性别。未知;
}
}
///
///将提供的性别设置为适当的“M”或“F”值。
///
///性别。
///
私有字符串SetGenderToString(对象对象objGender)
{
性别=(性别)objGender;
开关(性别)
{
案件性别:女性:
返回“F”;
案件性别:男:
返回“M”;
违约:
返回null;
}
}
公共方法信息方法
{
获取{return null;}
}
公共字符串PropertyName
{
获取{return\u property.Name;}
}
公共对象GetForInsert(对象所有者、IDictionary合并映射、ISessionImplementor会话)
{
返回获取(所有者);
}
公共类型返回类型
{
获取{return typeof(byte[]);}
}
}
#端区
公共IGetter getter(键入类、字符串属性名称)
{
返回新的GenderGetterSetter(class.GetProperty(propertyName));
}
公共ISetter GetSetter(键入类、字符串属性名称)
{
返回新的GenderGetterSetter(class.GetProperty(propertyName));
}
公共bool可以通过reflectionOptimizer访问
{
获取{return false;}
}
}
由于不太熟悉反射,我根本不确定Get和Set方法是否正确实现
当我尝试此操作时,仍然会出现一个错误“无法将F解析为性别”。我试过调试GenderPropertyAccessor类。映射文件中的相关行(如上所示)正在正确执行,GenderGetterSetter类的构造函数也在正确执行,但从未调用Get和Set方法
有人能告诉我我可能做错了什么吗?我会为此使用IUserType的实现。这是一个例子。在NullSafeGet和NullSafeSet方法中,您将分别将字符串变异为枚举和返回。为了使NHibernate能够检测到更改,Equals实现是否正确也是至关重要的 将属性映射为使用自定义用户类型很容易:
Map(x => x.Gender).Column("LS_GENDER").CustomType(typeof(MyUserType));
Jamie,这会正确地将'F'/'M'转换为性别枚举,但是当我使用Linq查询性别属性时,我得到以下结果:NHibernate.criteria.SimpleExpression:deased.Gender预期类型Kctc.NHibernate.Lawbase.UserTypes.GenderUserType,实际类型Kctc.GenderMy抱歉。我将ReturnedType设置为returntypeof(MyUserType),而不是typeof(Gender)。现在修复了这个,它工作得很好!谢谢你在我的日子里洒了点星尘。不客气。从你的头像判断,你可能想暂时抛开星尘。或者双倍剂量,由你决定。:-)一定要测试Equals实现,这让我不止一次绊倒。