我有一个名为 Entity 的基类:
public class Entity
{
public int Id {get;set;}
}
假设我有一个名为 Customer 的类:
public class Customer : Entity
{
public string Name {get;set;}
}
现在,通过 NHibernate 3.3.1 中的代码使用基于约定的映射,我尝试以下操作:
public static class DataHelper
{
private static HbmMapping GetMappings()
{
var mapper = new CustomModelMapper(typeof(Entity));
return mapper.CompileMappingFor(
typeof(DataHelper).Assembly.GetExportedTypes()
.Where(x => x.IsSubclassOf(typeof(Entity))));
}
}
当我尝试运行我的应用程序时,我收到错误“无法扩展未映射的类:实体”。我不想映射 Entity 类——它只是一个用于继承一些公共属性的基类。如何告诉 NHibernate 忽略未映射的类?作为参考,下面列出了我的 CustomModelMapper 类。
下面列出了我的 CustomModelMapper 类的代码以供参考
internal class CustomModelMapper : ConventionModelMapper
{
private const int DEFAULT_STRING_LENGTH = 100;
private Type baseType;
public CustomModelMapper(Type baseType)
{
this.baseType = baseType;
}
public CustomModelMapper()
{
SetupInspectors();
}
protected override void AppendDefaultEvents()
{
base.AppendDefaultEvents();
BeforeMapClass += OnBeforeMapClass;
BeforeMapProperty += OnBeforeMapProperty;
BeforeMapManyToOne += OnBeforeMapManyToOne;
BeforeMapBag += OnBeforeMapBag;
BeforeMapList += OnBeforeMapList;
BeforeMapSet += OnBeforeMapSet;
}
protected void OnBeforeMapClass(IModelInspector modelInspector, Type type, IClassAttributesMapper classCustomizer)
{
classCustomizer.Id(type.GetProperty("Id"), m => m.Generator(Generators.Native));
}
protected void OnBeforeMapProperty(IModelInspector modelInspector, PropertyPath member, IPropertyMapper propertyCustomizer)
{
if (member.LocalMember.GetPropertyOrFieldType().IsEnum)
{
var type = member.LocalMember.GetPropertyOrFieldType();
var genericType = typeof(EnumStringType<>).MakeGenericType(type);
propertyCustomizer.Type(genericType, null);
}
if (member.LocalMember.GetPropertyOrFieldType() == typeof(string))
propertyCustomizer.Length(DEFAULT_STRING_LENGTH);
}
protected void OnBeforeMapManyToOne(IModelInspector modelInspector, PropertyPath member, IManyToOneMapper propertyCustomizer)
{
propertyCustomizer.Cascade(Cascade.All);
propertyCustomizer.Fetch(FetchKind.Join);
propertyCustomizer.Lazy(LazyRelation.NoLazy);
propertyCustomizer.Index(string.Format("IX{0}{1}",
member.GetContainerEntity(modelInspector).Name,
member.LocalMember.Name));
}
protected void OnBeforeMapBag(IModelInspector modelInspector, PropertyPath member, IBagPropertiesMapper propertyCustomizer)
{
propertyCustomizer.Cascade(Cascade.All);
propertyCustomizer.Lazy(CollectionLazy.Extra);
propertyCustomizer.Fetch(CollectionFetchMode.Subselect);
}
protected void OnBeforeMapList(IModelInspector modelInspector, PropertyPath member, IListPropertiesMapper propertyCustomizer)
{
propertyCustomizer.Cascade(Cascade.All);
propertyCustomizer.Lazy(CollectionLazy.Extra);
propertyCustomizer.Fetch(CollectionFetchMode.Subselect);
}
protected void OnBeforeMapSet(IModelInspector modelInspector, PropertyPath member, ISetPropertiesMapper propertyCustomizer)
{
propertyCustomizer.Cascade(Cascade.All);
propertyCustomizer.Lazy(CollectionLazy.Extra);
propertyCustomizer.Fetch(CollectionFetchMode.Subselect);
}
protected void SetupInspectors()
{
IsRootEntity((type, declared) =>
{
return baseType.Equals(type.BaseType);
});
IsEntity((type, declared) =>
{
return baseType.IsAssignableFrom(type) && !type.IsInterface;
});
IsVersion((member, declared) =>
{
return
member.Name == "Version" &&
member.MemberType == MemberTypes.Property &&
member.GetPropertyOrFieldType() == typeof(int);
});
IsBag((member, declared) =>
{
if (member.GetPropertyOrFieldType().IsGenericType)
return IsGenericType(member, typeof(ICollection<>));
return false;
});
IsList((member, declared) =>
{
if (member.GetPropertyOrFieldType().IsGenericType)
return IsGenericType(member, typeof(IList<>));
return false;
});
IsSet((member, declared) =>
{
if (member.GetPropertyOrFieldType().IsGenericType)
return IsGenericType(member, typeof(ICG.ISet<>));
return false;
});
}
protected static bool IsGenericType(MemberInfo member, Type targetType)
{
var type = member.GetPropertyOrFieldType();
var generics = type.GetGenericInterfaceTypeDefinitions();
return generics.Contains(targetType);
}
}