昊 天

nhibernate源码分析之一: 对象映射

        1. 持久对象映射文件
        关于持久对象映射文件,这里就不多说了,可参考nhibernate的例子和文档。
在nhibernate源代码的根目录里有一个nhibernate-mapping-2.0.xsd文档,这个文档是nhibernate用来对映射文件进行验证的,我们也可以借助相关软件用这个文档来验证映射文件的有效性。
        2. 映射信息的读取
        通过Configuration类,可以用多种方式读取映射信息,一些以Add开头的方法就是用来加入映射信息的,这些方法最终将调用Add(XmlDocument doc)。
//** Configuration.cs **
private Hashtable classes = new Hashtable();
classes集合用于存放所有的持久对象映射信息,它的Key为持久类的类型;Value为PermissionClass类的子类。

    private void Add(XmlDocument doc) 
        
{
            
try 
            
{
                Binder.dialect 
= Dialect.Dialect.GetDialect(properties);
                Binder.BindRoot( doc, CreateMappings());
            }
 
            
catch (MappingException me) 
            
{
                log.Error(
"Could not compile the mapping document", me);
                
throw me;
            }
 // end try/catch
        }

AddDocument方法调用Binder的静态方法BindRoot来绑定持久类映射信息。CreateMappings返回一个Mappings对象,此对象是一个简单封装了所有映射信息集合的类。

3. 建立对象映射信息
Binder类的BindRoot用于绑定映射信息中的所有映射内容。

//** Binder.cs **

        
public static void BindRoot(XmlDocument doc, Mappings model) 
        
{
            
// 

            
foreach(XmlNode n in hmNode.SelectNodes(nsPrefix + ":class", nsmgr) ) 
            
{
                RootClass rootclass 
= new RootClass();
                Binder.BindRootClass(n, rootclass, model);
                model.AddClass(rootclass);
            }


            
// 
        }

遍历所有的类映射节点,然后调用BindRootClass来绑定类映射信息,最后将类映射信息加到集合中。
其中RootClass为PermissionClass的子类。

public static void BindRootClass(XmlNode node, RootClass model, Mappings mappings) 
        
{
            BindClass(node, model, mappings);

            
//TABLENAME
            XmlAttribute tableNameNode = node.Attributes["table"];
            
string tableName = (tableNameNode==null)
                
? StringHelper.Unqualify( model.PersistentClazz.Name )
                : tableNameNode.Value;

            XmlAttribute schemaNode 
= node.Attributes["schema"];
            
string schema = schemaNode==null ? mappings.SchemaName : schemaNode.Value;
            Table table 
= mappings.AddTable(schema, tableName);
            model.Table 
= table;

            
// 

            PropertiesFromXML(node, model, mappings);
        }


        BindRootClass首先调用BindClass绑定持久类映射信息,然后调用PropertiesFromXML来绑定类属性。

        
public static void BindClass(XmlNode node, PersistentClass model, Mappings mapping) 
        
{ 
            
string className = node.Attributes["name"] == null ? null : node.Attributes["name"].Value;

            
// class
            try 
            
{
                model.PersistentClazz 
= ReflectHelper.ClassForName(className);
            }
 
            
catch ( Exception cnfe ) 
            
{
                
throw new MappingException( "persistent class not found", cnfe);
            }


            
// 
        }


BindClass通过反射来取得持久对象的类型。

protected static void PropertiesFromXML(XmlNode node, PersistentClass model, Mappings mappings) 
        
{
            
string path = model.Name;
            Table table 
= model.Table;

            
foreach(XmlNode subnode in node.ChildNodes) 
            
{
                CollectionType collectType 
= CollectionType.CollectionTypeFromString(name);
                Value value 
= null;
                
if (collectType!=null) 
                
{
                    value 
= new Value(table);
                    BindValue(subnode, value, 
true);
                }
 
                
else if ( "many-to-one".Equals(name) ) 
                
{
                    value 
= new ManyToOne(table);
                    BindManyToOne(subnode, (ManyToOne) value, propertyName, 
true);
                }
 
                
else if ( "any".Equals(name) ) 
                
{
                    value 
= new Any(table);
                    BindAny(subnode, (Any) value, 
true);
                }

                
else if ( "one-to-one".Equals(name) ) 
                
{
                    value 
= new OneToOne(table, model.Identifier );
                    BindOneToOne(subnode, (OneToOne) value, 
true);
                }
 
                
else if ( "property".Equals(name) ) 
                
{
                    value 
= new Value(table);
                    BindValue(subnode, value, 
true, propertyName);
                }
 
                
else if ( "component".Equals(name) ) 
                
{
                    value 
= new Component(model);
                    BindComponent(subnode, (Component) value, reflectedClass, subpath, 
true, mappings);
                }
 
                
else if ( "subclass".Equals(name) ) 
                
{
                    Subclass subclass 
= new Subclass(model);
                    BindSubclass( subnode, subclass, mappings );
                }
 
                
else if ( "joined-subclass".Equals(name) ) 
                
{
                    Subclass subclass 
= new Subclass(model);
                    BindJoinedSubclass( subnode, subclass, mappings);
                }

                
if ( value!=null) 
                
{
                    Property prop 
= new Property(value);
                    BindProperty(subnode, prop, mappings);
                }

            }

        }


遍历所有子节点,然后根据节点类型对进行绑定。(注: 部分内容已删除)
关于属性的映射以后有空再详细研究,只需要知道属性已加入到RootClass的Properties属性就行了。

posted on 2006-04-18 15:48  Tutuya  阅读(316)  评论(0)    收藏  举报