1 //------------------------------------------------------------------------------
2 // <copyright file="XmlQualifiedName.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">Microsoft</owner>
6 //------------------------------------------------------------------------------
9 using System.Collections;
10 using System.Diagnostics;
12 using Microsoft.Win32;
13 using System.Reflection;
14 using System.Security;
15 using System.Security.Permissions;
18 /// <include file='doc\XmlQualifiedName.uex' path='docs/doc[@for="XmlQualifiedName"]/*' />
20 /// <para>[To be supplied.]</para>
25 public class XmlQualifiedName {
27 delegate int HashCodeOfStringDelegate(string s, int sLen, long additionalEntropy);
28 static HashCodeOfStringDelegate hashCodeDelegate = null;
38 /// <include file='doc\XmlQualifiedName.uex' path='docs/doc[@for="XmlQualifiedName.Empty"]/*' />
40 /// <para>[To be supplied.]</para>
42 public static readonly XmlQualifiedName Empty = new XmlQualifiedName(string.Empty);
44 /// <include file='doc\XmlQualifiedName.uex' path='docs/doc[@for="XmlQualifiedName.XmlQualifiedName"]/*' />
46 /// <para>[To be supplied.]</para>
48 public XmlQualifiedName() : this(string.Empty, string.Empty) {}
50 /// <include file='doc\XmlQualifiedName.uex' path='docs/doc[@for="XmlQualifiedName.XmlQualifiedName1"]/*' />
52 /// <para>[To be supplied.]</para>
54 public XmlQualifiedName(string name) : this(name, string.Empty) {}
56 /// <include file='doc\XmlQualifiedName.uex' path='docs/doc[@for="XmlQualifiedName.XmlQualifiedName2"]/*' />
58 /// <para>[To be supplied.]</para>
60 public XmlQualifiedName(string name, string ns) {
61 this.ns = ns == null ? string.Empty : ns;
62 this.name = name == null ? string.Empty : name;
65 /// <include file='doc\XmlQualifiedName.uex' path='docs/doc[@for="XmlQualifiedName.Namespace"]/*' />
67 /// <para>[To be supplied.]</para>
69 public string Namespace {
73 /// <include file='doc\XmlQualifiedName.uex' path='docs/doc[@for="XmlQualifiedName.Name"]/*' />
75 /// <para>[To be supplied.]</para>
81 /// <include file='doc\XmlQualifiedName.uex' path='docs/doc[@for="XmlQualifiedName.GetHashCode"]/*' />
83 /// <para>[To be supplied.]</para>
85 public override int GetHashCode() {
88 if (hashCodeDelegate == null) {
89 hashCodeDelegate = GetHashCodeDelegate();
92 hash = hashCodeDelegate(Name, Name.Length, 0);
95 hash = Name.GetHashCode() /*+ Namespace.GetHashCode()*/; // for perf reasons we are not taking ns's hashcode.
101 /// <include file='doc\XmlQualifiedName.uex' path='docs/doc[@for="XmlQualifiedName.IsEmpty"]/*' />
103 /// <para>[To be supplied.]</para>
105 public bool IsEmpty {
106 get { return Name.Length == 0 && Namespace.Length == 0; }
109 /// <include file='doc\XmlQualifiedName.uex' path='docs/doc[@for="XmlQualifiedName.ToString"]/*' />
111 /// <para>[To be supplied.]</para>
113 public override string ToString() {
114 return Namespace.Length == 0 ? Name : string.Concat(Namespace, ":" , Name);
117 /// <include file='doc\XmlQualifiedName.uex' path='docs/doc[@for="XmlQualifiedName.Equals"]/*' />
119 /// <para>[To be supplied.]</para>
121 public override bool Equals(object other) {
122 XmlQualifiedName qname;
124 if ((object) this == other) {
128 qname = other as XmlQualifiedName;
130 return (Name == qname.Name && Namespace == qname.Namespace);
135 /// <include file='doc\XmlQualifiedName.uex' path='docs/doc[@for="XmlQualifiedName.operator=="]/*' />
137 /// <para>[To be supplied.]</para>
139 public static bool operator ==(XmlQualifiedName a, XmlQualifiedName b) {
140 if ((object) a == (object) b)
143 if ((object) a == null || (object) b == null)
146 return (a.Name == b.Name && a.Namespace == b.Namespace);
149 /// <include file='doc\XmlQualifiedName.uex' path='docs/doc[@for="XmlQualifiedName.operator!="]/*' />
151 /// <para>[To be supplied.]</para>
153 public static bool operator !=(XmlQualifiedName a, XmlQualifiedName b) {
157 /// <include file='doc\XmlQualifiedName.uex' path='docs/doc[@for="XmlQualifiedName.ToString1"]/*' />
159 /// <para>[To be supplied.]</para>
161 public static string ToString(string name, string ns) {
162 return ns == null || ns.Length == 0 ? name : ns + ":" + name;
165 #if !SILVERLIGHT // These methods are not used in Silverlight
166 [SecuritySafeCritical]
168 [ReflectionPermission(SecurityAction.Assert, Unrestricted = true)]
170 private static HashCodeOfStringDelegate GetHashCodeDelegate() {
171 // If we are using randomized hashing and we find the Marving hash method, we use that
172 // Otherwise, we use the old string hashing function.
174 if (!IsRandomizedHashingDisabled())
176 MethodInfo getHashCodeMethodInfo = typeof(String).GetMethod("InternalMarvin32HashString", BindingFlags.NonPublic | BindingFlags.Static);
177 if (getHashCodeMethodInfo != null)
179 return (HashCodeOfStringDelegate)Delegate.CreateDelegate(typeof(HashCodeOfStringDelegate), getHashCodeMethodInfo);
181 // This will fall through and return a delegate to the old hash function
182 Debug.Assert(false, "Randomized hashing is not supported.");
184 return new HashCodeOfStringDelegate(GetHashCodeOfString);
188 static bool IsRandomizedHashingDisabled ()
193 [SecuritySafeCritical]
194 [RegistryPermission(SecurityAction.Assert, Unrestricted = true)]
195 private static bool IsRandomizedHashingDisabled() {
196 const string regValueName = "DisableRandomizedHashingOnXmlQualifiedName";
197 bool disableHashing = false; // default value
198 if (!ReadBoolFromXmlRegistrySettings(Registry.CurrentUser, regValueName, ref disableHashing)) {
199 ReadBoolFromXmlRegistrySettings(Registry.LocalMachine, regValueName, ref disableHashing);
201 return disableHashing;
205 private static bool ReadBoolFromXmlRegistrySettings(RegistryKey hive, string regValueName, ref bool value) {
206 const string regValuePath = @"SOFTWARE\Microsoft\.NETFramework\XML";
208 using (RegistryKey xmlRegKey = hive.OpenSubKey(regValuePath, false)) {
209 if (xmlRegKey != null) {
210 if (xmlRegKey.GetValueKind(regValueName) == RegistryValueKind.DWord) {
211 value = ((int)xmlRegKey.GetValue(regValueName)) == 1;
217 catch { /* use the default if we couldn't read the key */ }
221 private static int GetHashCodeOfString(string s, int length, long additionalEntropy)
223 // This is the fallback method for calling the regular hashcode method
224 return s.GetHashCode();
227 // --------- Some useful internal stuff -----------------
228 internal void Init(string name, string ns) {
229 Debug.Assert(name != null && ns != null);
235 internal void SetNamespace(string ns) {
236 Debug.Assert(ns != null);
237 this.ns = ns; //Not changing hash since ns is not used to compute hashcode
240 internal void Verify() {
241 XmlConvert.VerifyNCName(name);
242 if (ns.Length != 0) {
243 XmlConvert.ToUri(ns);
247 internal void Atomize(XmlNameTable nameTable) {
248 Debug.Assert(name != null);
249 name = nameTable.Add(name);
250 ns = nameTable.Add(ns);
253 internal static XmlQualifiedName Parse(string s, IXmlNamespaceResolver nsmgr, out string prefix) {
255 ValidateNames.ParseQNameThrow(s, out prefix, out localName);
257 string uri = nsmgr.LookupNamespace(prefix);
259 if (prefix.Length != 0) {
260 throw new XmlException(Res.Xml_UnknownNs, prefix);
262 else { //Re-map namespace of empty prefix to string.Empty when there is no default namespace declared
266 return new XmlQualifiedName(localName, uri);
269 internal XmlQualifiedName Clone() {
270 return (XmlQualifiedName)MemberwiseClone();
273 internal static int Compare(XmlQualifiedName a, XmlQualifiedName b) {
275 return (null == b) ? 0 : -1;
280 int i = String.CompareOrdinal(a.Namespace, b.Namespace);
282 i = String.CompareOrdinal(a.Name, b.Name);