日期:2009-06-07  浏览次数:20480 次

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,