ContentType TryCreate(string typeName, int recurse) {
				var ct = TryGet(typeName);
				if (ct != null)
					return ct;

				const int MAX_RECURSE = 1000;
				Debug.Assert(recurse <= MAX_RECURSE);
				if (recurse > MAX_RECURSE)
					return null;

				RawContentType rawCt;
				bool b = rawContentTypes.TryGetValue(typeName, out rawCt);
				Debug.Assert(b);
				if (!b)
					return null;
				b = rawContentTypes.Remove(rawCt.Typename);
				Debug.Assert(b);

				var baseTypes = new ContentType[rawCt.BaseTypes.Length];
				for (int i = 0; i < baseTypes.Length; i++) {
					var btContentType = TryCreate(rawCt.BaseTypes[i], recurse + 1);
					if (btContentType == null)
						return null;
					baseTypes[i] = btContentType;
				}

				ct = new ContentType(rawCt.Typename, baseTypes);
				owner.contentTypes.Add(ct.TypeName, ct);
				return ct;
			}
		IContentType AddContentTypeInternal_NoLock(string typeName, IEnumerable<string> baseTypesEnumerable) {
			if (contentTypes.ContainsKey(typeName))
				throw new ArgumentException("Content type already exists", nameof(typeName));
			var btGuids = baseTypesEnumerable.ToArray();
			if (btGuids.Any(a => a == UnknownContentTypeName))
				throw new ArgumentException("Can't derive from the unknown content type", nameof(baseTypesEnumerable));
			var baseTypes = baseTypesEnumerable.Select(a => GetContentType(a)).ToArray();
			var ct = new ContentType(typeName, baseTypes);
			contentTypes.Add(ct.TypeName, ct);
			return ct;
		}