我一直在使用NHibernate> = 3.2中的代码功能进行NHibernate映射,非常喜欢它。现在我想在现有项目中开始使用它,我们有大约80个*.hbm.xml
个文件。一次性更改所有*.hbm.xml
文件是不可行的,因此我希望使用代码映射新映射,并逐步转换现有XML文件。
我尝试将一个XML文件转换为按代码映射,并修改了我的配置构建代码以引入代码映射。以下是代码的摘录:
private void AddMappings(Configuration configuration, Assembly assembly)
{
// add mappings from embedded *.hbm.xml files
configuration.AddAssembly(assembly);
// add mappings from map by code
var modelMapper = new ModelMapper();
modelMapper.AddMappings(assembly.GetExportedTypes());
var mapping = modelMapper.CompileMappingForAllExplicitlyAddedEntities();
configuration.AddMapping(mapping);
}
我发现XML文件中的实体已添加到配置中,但我的代码类映射未添加。
有关我做错的任何建议吗?
答案 0 :(得分:0)
这是我用来做你想做的代码:
private IHibernateConfigurationExtension m_ExtensionConfig;
private Configuration m_Configuration;
public Configuration Configuration
{
get
{
if (m_Configuration == null)
{
m_ExtensionConfig = FetchExtensionConfig();
m_Configuration = new Configuration();
string assemblyDirectory = Path.GetDirectoryName(m_ExtensionConfig.Assembly.Location);
m_Configuration.Configure(Path.Combine(assemblyDirectory, "hibernate.cfg.xml"));
m_Configuration = LoadHBMXML(m_Configuration);
m_Configuration = LoadMappings(m_Configuration);
}
return m_Configuration;
}
}
#region NHibernate Configuration
/// <summary>
/// Load the assemblies that are configured with the *.hbm.xml configuration
/// </summary>
/// <param name="configuration"></param>
/// <returns></returns>
private Configuration LoadHBMXML(Configuration configuration)
{
configuration.AddAssembly(m_ExtensionConfig.Assembly);
return configuration;
}
/// <summary>
/// Load the configurations that are configured with the ClassMap convention (NHibernate 3.2+)
/// </summary>
/// <param name="configuration"></param>
/// <returns></returns>
private Configuration LoadMappings(Configuration configuration)
{
// This configuration for mapper files
ModelMapper mapper = new ModelMapper();
mapper.BeforeMapProperty += new PropertyMappingHandler(mapper_BeforeMapProperty);
List<Type> typeList = m_ExtensionConfig.Assembly.GetMatchingTypesInAssembly(item => m_ExtensionConfig.MappingsNamespace.Equals(item.Namespace)).ToList();
mapper.AddMappings(typeList);
IEnumerable<HbmMapping> mappings = mapper.CompileMappingForEachExplicitlyAddedEntity();
mappings.ForEach(m => configuration.AddMapping(m));
if (DumpToXML)
mappings.WriteAllXmlMapping();
return configuration;
}
我使用的界面
/// <summary>
/// An interface to be implemented within the assembly using the
/// HibernateDAO class. This determines what gets configured
/// for hibernate automatically.
/// <para>NOTE: Currently only supports a single implementation
/// within all loaded assemblies</para>
/// </summary>
public interface IHibernateConfigurationExtension
{
/// <summary>
/// The namespace containing the mapping files.
/// <para>Only a single namespace is currently supported</para>
/// </summary>
string MappingsNamespace { get; }
/// <summary>
/// The assembly to search for .hbm.xml hibernate configuration files
/// </summary>
Assembly Assembly { get; }
/// <summary>
/// Dictionary of conversion mappings
/// <para>Type is the object type, the type used in object definitions</para>
/// <para>Type of IUserType is the NHIbernate IUserType implementation to convert
/// between the Type and the persisted representation</para>
/// </summary>
IDictionary<Type, Type> UserConversionMappings { get; }
}
获取扩展配置的方法
/// <summary>
/// Fetch the class that implements the IHibernateConfigurationExtension interface
/// <para>Support is only provided for a single implementation of this class
/// through all loaded assemblies</para>
/// </summary>
/// <returns>The class that implements the extension</returns>
private IHibernateConfigurationExtension FetchExtensionConfig()
{
ICollection<Type> interfaces = AssemblyUtils.GetMatchingTypes(item => item.GetInterfaces().Contains(typeof(IHibernateConfigurationExtension)));
if (interfaces.Count == 0)
throw new ArgumentException("No implementation of IHibernateConfigurationExtension found");
if (interfaces.Count > 1)
throw new ArgumentException("Only support for a single implementation if IHibernateConfigurationExtension available. Please raise support request");
return Activator.CreateInstance(interfaces.First()) as IHibernateConfigurationExtension;
}
需要的AssemblyUtils中的部分
/// <summary>
/// Get all matching types in all assemblies that match the predicate
/// </summary>
/// <param name="predicate">The predicate function to match the types against</param>
/// <returns>The list of all types that match the predicate</returns>
public static ICollection<Type> GetMatchingTypes(Predicate<Type> predicate)
{
ICollection<Type> types = new List<Type>();
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
try
{
types.AddRange(assembly.GetTypes().Where(i => i != null && predicate(i)).ToList());
}
catch (ReflectionTypeLoadException ex)
{
types.AddRange(ProcessExceptionTypes(ex.Types, i => i != null && predicate(i)));
}
}
return types;
}
/// <summary>
/// Process each of the types in the list (usually called from within a ReflectionTypeLoadException
/// to load the types that match the predicate.
/// </summary>
/// <param name="theTypes">The list of types to process (taken from ReflectionTypeLoadException.Types</param>
/// <param name="predicate">The boolean predicate to compare the type against</param>
/// <returns>The collection of types (that can be loaded) matching the predicate</returns>
private static ICollection<Type> ProcessExceptionTypes(Type[] theTypes, Predicate<Type> predicate)
{
ICollection<Type> types = new List<Type>();
foreach (Type theType in theTypes)
{
try
{
if (predicate(theType))
types.Add(theType);
}
// This exception list is not exhaustive, modify to suit any reasons
// you find for failure to parse a single assembly
catch (BadImageFormatException)
{
// Type not in this assembly - reference to elsewhere ignored
}
catch (FileNotFoundException)
{
// Type not in this assembly - reference to elsewhere ignored
}
}
return types;
}