⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 collectionbinder.cs

📁 NHibernate NET开发者所需的
💻 CS
📖 第 1 页 / 共 2 页
字号:
using System;
using System.Collections.Generic;
using System.Xml;

using NHibernate.Mapping;
using NHibernate.Type;
using NHibernate.Util;

using Array = NHibernate.Mapping.Array;

namespace NHibernate.Cfg.XmlHbmBinding
{
	public class CollectionBinder : ClassBinder
	{
		private readonly IDictionary<string, CreateCollectionCommand> createCollectionCommands =
			new Dictionary<string, CreateCollectionCommand>();

		public CollectionBinder(ClassBinder parent)
			: base(parent)
		{
			CreateCommandCollection();
		}

		private void CreateCommandCollection()
		{
			createCollectionCommands.Add("map", CreateMap);
			createCollectionCommands.Add("bag", CreateBag);
			createCollectionCommands.Add("idbag", CreateIdentifierBag);
			createCollectionCommands.Add("set", CreateSet);
			createCollectionCommands.Add("list", CreateList);
			createCollectionCommands.Add("array", CreateArray);
			createCollectionCommands.Add("primitive-array", CreatePrimitiveArray);
		}

		public bool CanCreate(string xmlTagName)
		{
			return createCollectionCommands.ContainsKey(xmlTagName);
		}

		public Mapping.Collection Create(string xmlTagName, XmlNode node, string className,
			string path, PersistentClass owner, System.Type containingType)
		{
			CreateCollectionCommand command = createCollectionCommands[xmlTagName];
			return command(node, className, path, owner, containingType);
		}

		private Mapping.Collection CreateMap(XmlNode node, string prefix, string path,
			PersistentClass owner, System.Type containingType)
		{
			Map map = new Map(owner);
			BindCollection(node, map, prefix, path, containingType);
			return map;
		}

		private Mapping.Collection CreateSet(XmlNode node, string prefix, string path,
			PersistentClass owner, System.Type containingType)
		{
			Set setCollection = new Set(owner);
			BindCollection(node, setCollection, prefix, path, containingType);
			return setCollection;
		}

		private Mapping.Collection CreateList(XmlNode node, string prefix, string path,
			PersistentClass owner, System.Type containingType)
		{
			List list = new List(owner);
			BindCollection(node, list, prefix, path, containingType);
			return list;
		}

		private Mapping.Collection CreateBag(XmlNode node, string prefix, string path,
			PersistentClass owner, System.Type containingType)
		{
			Bag bag = new Bag(owner);
			BindCollection(node, bag, prefix, path, containingType);
			return bag;
		}

		private Mapping.Collection CreateIdentifierBag(XmlNode node, string prefix, string path,
			PersistentClass owner, System.Type containingType)
		{
			IdentifierBag bag = new IdentifierBag(owner);
			BindCollection(node, bag, prefix, path, containingType);
			return bag;
		}

		private Mapping.Collection CreateArray(XmlNode node, string prefix, string path,
			PersistentClass owner, System.Type containingType)
		{
			Array array = new Array(owner);
			BindArray(node, array, prefix, path, containingType);
			return array;
		}

		private Mapping.Collection CreatePrimitiveArray(XmlNode node, string prefix, string path,
			PersistentClass owner, System.Type containingType)
		{
			PrimitiveArray array = new PrimitiveArray(owner);
			BindArray(node, array, prefix, path, containingType);
			return array;
		}

		/// <remarks>
		/// Called for all collections. <paramref name="containingType" /> parameter
		/// was added in NH to allow for reflection related to generic types.
		/// </remarks>
		private void BindCollection(XmlNode node, Mapping.Collection model, string className,
			string path, System.Type containingType)
		{
			// ROLENAME
			model.Role = StringHelper.Qualify(className, path);
			// TODO: H3.1 has just collection.setRole(path) here - why?

			XmlAttribute inverseNode = node.Attributes["inverse"];
			if (inverseNode != null)
				model.IsInverse = StringHelper.BooleanValue(inverseNode.Value);

			// TODO: H3.1 - not ported: mutable
			XmlAttribute olNode = node.Attributes["optimistic-lock"];
			model.IsOptimisticLocked = olNode == null || "true".Equals(olNode.Value);

			XmlAttribute orderNode = node.Attributes["order-by"];
			if (orderNode != null)
				model.OrderBy = orderNode.Value;
			XmlAttribute whereNode = node.Attributes["where"];
			if (whereNode != null)
				model.Where = whereNode.Value;
			XmlAttribute batchNode = node.Attributes["batch-size"];
			if (batchNode != null)
				model.BatchSize = int.Parse(batchNode.Value);

			// PERSISTER
			XmlAttribute persisterNode = node.Attributes["persister"];
			if (persisterNode == null)
			{
				//persister = CollectionPersisterImpl.class;
			}
			else
				model.CollectionPersisterClass = ClassForNameChecked(
					persisterNode.Value, mappings,
					"could not instantiate collection persister class: {0}");

			XmlAttribute typeNode = node.Attributes["collection-type"];
			if (typeNode != null)
				model.TypeName = typeNode.Value;

			// FETCH STRATEGY
			InitOuterJoinFetchSetting(node, model);

			if ("subselect".Equals(XmlHelper.GetAttributeValue(node, "fetch")))
			{
				model.IsSubselectLoadable = true;
				model.Owner.HasSubselectLoadableCollections = true;
			}

			// LAZINESS
			InitLaziness(node, model, "true", mappings.DefaultLazy);
			// TODO: H3.1 - lazy="extra"

			XmlNode oneToManyNode = node.SelectSingleNode(HbmConstants.nsOneToMany, namespaceManager);
			if (oneToManyNode != null)
			{
				OneToMany oneToMany = new OneToMany(model.Owner);
				model.Element = oneToMany;
				BindOneToMany(oneToManyNode, oneToMany);
				//we have to set up the table later!! yuck
			}
			else
			{
				//TABLE
				XmlAttribute tableNode = node.Attributes["table"];
				string tableName;
				if (tableNode != null)
					tableName = mappings.NamingStrategy.TableName(tableNode.Value);
				else
					tableName = mappings.NamingStrategy.PropertyToTableName(className, path);
				XmlAttribute schemaNode = node.Attributes["schema"];
				string schema = schemaNode == null ? mappings.SchemaName : schemaNode.Value;
				XmlAttribute catalogNode = node.Attributes["catalog"];
				string catalog = catalogNode == null ? mappings.CatalogName : catalogNode.Value;

				model.CollectionTable = mappings.AddTable(schema, catalog, tableName, null, false);

				log.InfoFormat("Mapping collection: {0} -> {1}", model.Role, model.CollectionTable.Name);
			}

			//SORT
			XmlAttribute sortedAtt = node.Attributes["sort"];
			// unsorted, natural, comparator.class.name
			if (sortedAtt == null || sortedAtt.Value.Equals("unsorted"))
				model.IsSorted = false;
			else
			{
				model.IsSorted = true;
				if (!sortedAtt.Value.Equals("natural"))
				{
					string comparatorClassName = FullClassName(sortedAtt.Value, mappings);
					try
					{
						model.Comparer = Activator.CreateInstance(ReflectHelper.ClassForName(comparatorClassName));
					}
					catch
					{
						throw new MappingException("could not instantiate comparer class: " + comparatorClassName);
					}
				}
			}

			//ORPHAN DELETE (used for programmer error detection)
			XmlAttribute cascadeAtt = node.Attributes["cascade"];
			if (cascadeAtt != null && cascadeAtt.Value.Equals("all-delete-orphan"))
				model.HasOrphanDelete = true;

			bool? isGeneric = null;

			XmlAttribute genericAtt = node.Attributes["generic"];
			if (genericAtt != null)
				isGeneric = bool.Parse(genericAtt.Value);

			System.Type collectionType = null;

			if (!isGeneric.HasValue && containingType != null)
			{
				collectionType = GetPropertyType(node, containingType, GetPropertyName(node));
				isGeneric = collectionType.IsGenericType;
			}

			model.IsGeneric = isGeneric ?? false;

			if (model.IsGeneric)
			{
				// Determine the generic arguments using reflection
				if (collectionType == null)
					collectionType = GetPropertyType(node, containingType, GetPropertyName(node));
				System.Type[] genericArguments = collectionType.GetGenericArguments();
				model.GenericArguments = genericArguments;
			}

			HandleCustomSQL(node, model);

			//set up second pass
			if (model is List)
				AddListSecondPass(node, (List)model);

			else if (model is Map)
				AddMapSecondPass(node, (Map)model);

			else if (model is Set)
				AddSetSecondPass(node, (Set)model);

			else if (model is IdentifierCollection)
				AddIdentifierCollectionSecondPass(node, (IdentifierCollection)model);

			else
				AddCollectionSecondPass(node, model);

			foreach (XmlNode filter in node.SelectNodes(HbmConstants.nsFilter, namespaceManager))
				ParseFilter(filter, model);

			XmlNode loader = node.SelectSingleNode(HbmConstants.nsLoader, namespaceManager);
			if (loader != null)
				model.LoaderName = XmlHelper.GetAttributeValue(loader, "query-ref");

			XmlNode key = node.SelectSingleNode(HbmConstants.nsKey, namespaceManager);
			if (key != null)
				model.ReferencedPropertyName = XmlHelper.GetAttributeValue(key, "property-ref");

		}

		/// <remarks>
		/// Called for arrays and primitive arrays
		/// </remarks>
		private void BindArray(XmlNode node, Array model, string prefix, string path,
			System.Type containingType)
		{
			BindCollection(node, model, prefix, path, containingType);

			XmlAttribute att = node.Attributes["element-class"];

			if (att != null)
				model.ElementClassName = GetQualifiedClassName(att.Value, mappings);
			else
				foreach (XmlNode subnode in node.ChildNodes)
				{
					// TODO NH: mmm.... the code below, maybe, must be resolved by SecondPass (not here)
					string name = subnode.LocalName; //.Name;

					//I am only concerned with elements that are from the nhibernate namespace
					if (subnode.NamespaceURI != Configuration.MappingSchemaXMLNS)
						continue;

					switch (name)
					{
						case "element":
							string typeName;
							XmlAttribute typeAttribute = subnode.Attributes["type"];
							if (typeAttribute != null)
								typeName = typeAttribute.Value;
							else
								throw new MappingException("type for <element> was not defined");
							IType type = TypeFactory.HeuristicType(typeName, null);
							if (type == null)
								throw new MappingException("could not interpret type: " + typeName);

							model.ElementClassName = type.ReturnedClass.AssemblyQualifiedName;
							break;

						case "one-to-many":
						case "many-to-many":
						case "composite-element":
							model.ElementClassName = GetQualifiedClassName(subnode.Attributes["class"].Value, mappings);
							break;
					}
				}
		}

		private void AddListSecondPass(XmlNode node, List model)
		{
			mappings.AddSecondPass(delegate(IDictionary<string, PersistentClass> persistentClasses)
				{
					PreCollectionSecondPass(model);
					BindListSecondPass(node, model, persistentClasses);
					PostCollectionSecondPass(model);
				});
		}

		private void AddMapSecondPass(XmlNode node, Map model)
		{
			mappings.AddSecondPass(delegate(IDictionary<string, PersistentClass> persistentClasses)
				{
					PreCollectionSecondPass(model);
					BindMapSecondPass(node, model, persistentClasses);
					PostCollectionSecondPass(model);
				});

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -