NetDataContractSerializer.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  1. //------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.Runtime.Serialization
  5. {
  6. using System;
  7. using System.IO;
  8. using System.Xml;
  9. using System.Security;
  10. using System.Collections;
  11. using System.Security.Permissions;
  12. using System.Runtime.CompilerServices;
  13. using System.Runtime.Serialization.Formatters;
  14. using System.Collections.Generic;
  15. #if !NO_CONFIGURATION
  16. using System.Runtime.Serialization.Configuration;
  17. #endif
  18. using System.Reflection;
  19. public sealed class NetDataContractSerializer : XmlObjectSerializer, IFormatter
  20. {
  21. XmlDictionaryString rootName;
  22. XmlDictionaryString rootNamespace;
  23. StreamingContext context;
  24. SerializationBinder binder;
  25. ISurrogateSelector surrogateSelector;
  26. int maxItemsInObjectGraph;
  27. bool ignoreExtensionDataObject;
  28. FormatterAssemblyStyle assemblyFormat;
  29. DataContract cachedDataContract;
  30. static Hashtable typeNameCache = new Hashtable();
  31. public NetDataContractSerializer()
  32. : this(new StreamingContext(StreamingContextStates.All))
  33. {
  34. }
  35. public NetDataContractSerializer(StreamingContext context)
  36. : this(context, Int32.MaxValue, false, FormatterAssemblyStyle.Full, null)
  37. {
  38. }
  39. public NetDataContractSerializer(StreamingContext context,
  40. int maxItemsInObjectGraph,
  41. bool ignoreExtensionDataObject,
  42. FormatterAssemblyStyle assemblyFormat,
  43. ISurrogateSelector surrogateSelector)
  44. {
  45. Initialize(context, maxItemsInObjectGraph, ignoreExtensionDataObject, assemblyFormat, surrogateSelector);
  46. }
  47. public NetDataContractSerializer(string rootName, string rootNamespace)
  48. : this(rootName, rootNamespace, new StreamingContext(StreamingContextStates.All), Int32.MaxValue, false, FormatterAssemblyStyle.Full, null)
  49. {
  50. }
  51. public NetDataContractSerializer(string rootName, string rootNamespace,
  52. StreamingContext context,
  53. int maxItemsInObjectGraph,
  54. bool ignoreExtensionDataObject,
  55. FormatterAssemblyStyle assemblyFormat,
  56. ISurrogateSelector surrogateSelector)
  57. {
  58. XmlDictionary dictionary = new XmlDictionary(2);
  59. Initialize(dictionary.Add(rootName), dictionary.Add(DataContract.GetNamespace(rootNamespace)), context, maxItemsInObjectGraph, ignoreExtensionDataObject, assemblyFormat, surrogateSelector);
  60. }
  61. public NetDataContractSerializer(XmlDictionaryString rootName, XmlDictionaryString rootNamespace)
  62. : this(rootName, rootNamespace, new StreamingContext(StreamingContextStates.All), Int32.MaxValue, false, FormatterAssemblyStyle.Full, null)
  63. {
  64. }
  65. public NetDataContractSerializer(XmlDictionaryString rootName, XmlDictionaryString rootNamespace,
  66. StreamingContext context,
  67. int maxItemsInObjectGraph,
  68. bool ignoreExtensionDataObject,
  69. FormatterAssemblyStyle assemblyFormat,
  70. ISurrogateSelector surrogateSelector)
  71. {
  72. Initialize(rootName, rootNamespace, context, maxItemsInObjectGraph, ignoreExtensionDataObject, assemblyFormat, surrogateSelector);
  73. }
  74. void Initialize(StreamingContext context,
  75. int maxItemsInObjectGraph,
  76. bool ignoreExtensionDataObject,
  77. FormatterAssemblyStyle assemblyFormat,
  78. ISurrogateSelector surrogateSelector)
  79. {
  80. this.context = context;
  81. if (maxItemsInObjectGraph < 0)
  82. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("maxItemsInObjectGraph", SR.GetString(SR.ValueMustBeNonNegative)));
  83. this.maxItemsInObjectGraph = maxItemsInObjectGraph;
  84. this.ignoreExtensionDataObject = ignoreExtensionDataObject;
  85. this.surrogateSelector = surrogateSelector;
  86. this.AssemblyFormat = assemblyFormat;
  87. }
  88. void Initialize(XmlDictionaryString rootName, XmlDictionaryString rootNamespace,
  89. StreamingContext context,
  90. int maxItemsInObjectGraph,
  91. bool ignoreExtensionDataObject,
  92. FormatterAssemblyStyle assemblyFormat,
  93. ISurrogateSelector surrogateSelector)
  94. {
  95. Initialize(context, maxItemsInObjectGraph, ignoreExtensionDataObject, assemblyFormat, surrogateSelector);
  96. this.rootName = rootName;
  97. this.rootNamespace = rootNamespace;
  98. }
  99. static bool? unsafeTypeForwardingEnabled;
  100. internal static bool UnsafeTypeForwardingEnabled
  101. {
  102. [Fx.Tag.SecurityNote(Critical = "Calls Security Critical method NetDataContractSerializerSection.TryUnsafeGetSection.", Safe = "The ConfigSection instance is not leaked.")]
  103. [SecuritySafeCritical]
  104. get
  105. {
  106. if (unsafeTypeForwardingEnabled == null)
  107. {
  108. #if NO_CONFIGURATION
  109. unsafeTypeForwardingEnabled = false;
  110. #else
  111. NetDataContractSerializerSection section;
  112. if (NetDataContractSerializerSection.TryUnsafeGetSection(out section))
  113. {
  114. unsafeTypeForwardingEnabled = section.EnableUnsafeTypeForwarding;
  115. }
  116. else
  117. {
  118. unsafeTypeForwardingEnabled = false;
  119. }
  120. #endif
  121. }
  122. Fx.Assert(unsafeTypeForwardingEnabled != null, "unsafeTypeForwardingEnabled should not be null.");
  123. return unsafeTypeForwardingEnabled.Value;
  124. }
  125. }
  126. public StreamingContext Context
  127. {
  128. get { return context; }
  129. set { context = value; }
  130. }
  131. public SerializationBinder Binder
  132. {
  133. get { return binder; }
  134. set { binder = value; }
  135. }
  136. public ISurrogateSelector SurrogateSelector
  137. {
  138. get { return surrogateSelector; }
  139. set { surrogateSelector = value; }
  140. }
  141. public FormatterAssemblyStyle AssemblyFormat
  142. {
  143. get { return assemblyFormat; }
  144. set
  145. {
  146. if (value != FormatterAssemblyStyle.Full && value != FormatterAssemblyStyle.Simple)
  147. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.InvalidAssemblyFormat, value)));
  148. assemblyFormat = value;
  149. }
  150. }
  151. public int MaxItemsInObjectGraph
  152. {
  153. get { return maxItemsInObjectGraph; }
  154. }
  155. public bool IgnoreExtensionDataObject
  156. {
  157. get { return ignoreExtensionDataObject; }
  158. }
  159. public void Serialize(Stream stream, object graph)
  160. {
  161. base.WriteObject(stream, graph);
  162. }
  163. public object Deserialize(Stream stream)
  164. {
  165. return base.ReadObject(stream);
  166. }
  167. internal override void InternalWriteObject(XmlWriterDelegator writer, object graph)
  168. {
  169. Hashtable surrogateDataContracts = null;
  170. DataContract contract = GetDataContract(graph, ref surrogateDataContracts);
  171. InternalWriteStartObject(writer, graph, contract);
  172. InternalWriteObjectContent(writer, graph, contract, surrogateDataContracts);
  173. InternalWriteEndObject(writer);
  174. }
  175. public override void WriteObject(XmlWriter writer, object graph)
  176. {
  177. WriteObjectHandleExceptions(new XmlWriterDelegator(writer), graph);
  178. }
  179. public override void WriteStartObject(XmlWriter writer, object graph)
  180. {
  181. WriteStartObjectHandleExceptions(new XmlWriterDelegator(writer), graph);
  182. }
  183. public override void WriteObjectContent(XmlWriter writer, object graph)
  184. {
  185. WriteObjectContentHandleExceptions(new XmlWriterDelegator(writer), graph);
  186. }
  187. public override void WriteEndObject(XmlWriter writer)
  188. {
  189. WriteEndObjectHandleExceptions(new XmlWriterDelegator(writer));
  190. }
  191. public override void WriteStartObject(XmlDictionaryWriter writer, object graph)
  192. {
  193. WriteStartObjectHandleExceptions(new XmlWriterDelegator(writer), graph);
  194. }
  195. internal override void InternalWriteStartObject(XmlWriterDelegator writer, object graph)
  196. {
  197. Hashtable surrogateDataContracts = null;
  198. DataContract contract = GetDataContract(graph, ref surrogateDataContracts);
  199. InternalWriteStartObject(writer, graph, contract);
  200. }
  201. void InternalWriteStartObject(XmlWriterDelegator writer, object graph, DataContract contract)
  202. {
  203. WriteRootElement(writer, contract, rootName, rootNamespace, CheckIfNeedsContractNsAtRoot(rootName, rootNamespace, contract));
  204. }
  205. public override void WriteObjectContent(XmlDictionaryWriter writer, object graph)
  206. {
  207. WriteObjectContentHandleExceptions(new XmlWriterDelegator(writer), graph);
  208. }
  209. internal override void InternalWriteObjectContent(XmlWriterDelegator writer, object graph)
  210. {
  211. Hashtable surrogateDataContracts = null;
  212. DataContract contract = GetDataContract(graph, ref surrogateDataContracts);
  213. InternalWriteObjectContent(writer, graph, contract, surrogateDataContracts);
  214. }
  215. void InternalWriteObjectContent(XmlWriterDelegator writer, object graph, DataContract contract, Hashtable surrogateDataContracts)
  216. {
  217. if (MaxItemsInObjectGraph == 0)
  218. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.ExceededMaxItemsQuota, MaxItemsInObjectGraph)));
  219. if (IsRootXmlAny(rootName, contract))
  220. {
  221. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.IsAnyNotSupportedByNetDataContractSerializer, contract.UnderlyingType)));
  222. }
  223. else if (graph == null)
  224. {
  225. WriteNull(writer);
  226. }
  227. else
  228. {
  229. Type graphType = graph.GetType();
  230. if (contract.UnderlyingType != graphType)
  231. contract = GetDataContract(graph, ref surrogateDataContracts);
  232. XmlObjectSerializerWriteContext context = null;
  233. if (contract.CanContainReferences)
  234. {
  235. context = XmlObjectSerializerWriteContext.CreateContext(this, surrogateDataContracts);
  236. context.HandleGraphAtTopLevel(writer, graph, contract);
  237. }
  238. WriteClrTypeInfo(writer, contract, binder);
  239. contract.WriteXmlValue(writer, graph, context);
  240. }
  241. }
  242. // Update the overloads whenever you are changing this method
  243. internal static void WriteClrTypeInfo(XmlWriterDelegator writer, DataContract dataContract, SerializationBinder binder)
  244. {
  245. if (!dataContract.IsISerializable && !(dataContract is SurrogateDataContract))
  246. {
  247. TypeInformation typeInformation = null;
  248. Type clrType = dataContract.OriginalUnderlyingType;
  249. string clrTypeName = null;
  250. string clrAssemblyName = null;
  251. if (binder != null)
  252. {
  253. binder.BindToName(clrType, out clrAssemblyName, out clrTypeName);
  254. }
  255. if (clrTypeName == null)
  256. {
  257. typeInformation = NetDataContractSerializer.GetTypeInformation(clrType);
  258. clrTypeName = typeInformation.FullTypeName;
  259. }
  260. if (clrAssemblyName == null)
  261. {
  262. clrAssemblyName = (typeInformation == null) ?
  263. NetDataContractSerializer.GetTypeInformation(clrType).AssemblyString :
  264. typeInformation.AssemblyString;
  265. // Throw in the [TypeForwardedFrom] case to prevent a partially trusted assembly from forwarding itself to an assembly with higher privileges
  266. if (!UnsafeTypeForwardingEnabled && !clrType.Assembly.IsFullyTrusted && !IsAssemblyNameForwardingSafe(clrType.Assembly.FullName, clrAssemblyName))
  267. {
  268. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.TypeCannotBeForwardedFrom, DataContract.GetClrTypeFullName(clrType), clrType.Assembly.FullName, clrAssemblyName)));
  269. }
  270. }
  271. WriteClrTypeInfo(writer, clrTypeName, clrAssemblyName);
  272. }
  273. }
  274. // Update the overloads whenever you are changing this method
  275. internal static void WriteClrTypeInfo(XmlWriterDelegator writer, Type dataContractType, SerializationBinder binder, string defaultClrTypeName, string defaultClrAssemblyName)
  276. {
  277. string clrTypeName = null;
  278. string clrAssemblyName = null;
  279. if (binder != null)
  280. {
  281. binder.BindToName(dataContractType, out clrAssemblyName, out clrTypeName);
  282. }
  283. if (clrTypeName == null)
  284. {
  285. clrTypeName = defaultClrTypeName;
  286. }
  287. if (clrAssemblyName == null)
  288. {
  289. clrAssemblyName = defaultClrAssemblyName;
  290. }
  291. WriteClrTypeInfo(writer, clrTypeName, clrAssemblyName);
  292. }
  293. // Update the overloads whenever you are changing this method
  294. internal static void WriteClrTypeInfo(XmlWriterDelegator writer, Type dataContractType, SerializationBinder binder, SerializationInfo serInfo)
  295. {
  296. TypeInformation typeInformation = null;
  297. string clrTypeName = null;
  298. string clrAssemblyName = null;
  299. if (binder != null)
  300. {
  301. binder.BindToName(dataContractType, out clrAssemblyName, out clrTypeName);
  302. }
  303. if (clrTypeName == null)
  304. {
  305. if (serInfo.IsFullTypeNameSetExplicit)
  306. {
  307. clrTypeName = serInfo.FullTypeName;
  308. }
  309. else
  310. {
  311. typeInformation = NetDataContractSerializer.GetTypeInformation(serInfo.ObjectType);
  312. clrTypeName = typeInformation.FullTypeName;
  313. }
  314. }
  315. if (clrAssemblyName == null)
  316. {
  317. if (serInfo.IsAssemblyNameSetExplicit)
  318. {
  319. clrAssemblyName = serInfo.AssemblyName;
  320. }
  321. else
  322. {
  323. clrAssemblyName = (typeInformation == null) ?
  324. NetDataContractSerializer.GetTypeInformation(serInfo.ObjectType).AssemblyString :
  325. typeInformation.AssemblyString;
  326. }
  327. }
  328. WriteClrTypeInfo(writer, clrTypeName, clrAssemblyName);
  329. }
  330. static void WriteClrTypeInfo(XmlWriterDelegator writer, string clrTypeName, string clrAssemblyName)
  331. {
  332. if (clrTypeName != null)
  333. writer.WriteAttributeString(Globals.SerPrefix, DictionaryGlobals.ClrTypeLocalName, DictionaryGlobals.SerializationNamespace, DataContract.GetClrTypeString(clrTypeName));
  334. if (clrAssemblyName != null)
  335. writer.WriteAttributeString(Globals.SerPrefix, DictionaryGlobals.ClrAssemblyLocalName, DictionaryGlobals.SerializationNamespace, DataContract.GetClrTypeString(clrAssemblyName));
  336. }
  337. public override void WriteEndObject(XmlDictionaryWriter writer)
  338. {
  339. WriteEndObjectHandleExceptions(new XmlWriterDelegator(writer));
  340. }
  341. internal override void InternalWriteEndObject(XmlWriterDelegator writer)
  342. {
  343. writer.WriteEndElement();
  344. }
  345. public override object ReadObject(XmlReader reader)
  346. {
  347. return ReadObjectHandleExceptions(new XmlReaderDelegator(reader), true /*verifyObjectName*/);
  348. }
  349. public override object ReadObject(XmlReader reader, bool verifyObjectName)
  350. {
  351. return ReadObjectHandleExceptions(new XmlReaderDelegator(reader), verifyObjectName);
  352. }
  353. public override bool IsStartObject(XmlReader reader)
  354. {
  355. return IsStartObjectHandleExceptions(new XmlReaderDelegator(reader));
  356. }
  357. public override object ReadObject(XmlDictionaryReader reader, bool verifyObjectName)
  358. {
  359. return ReadObjectHandleExceptions(new XmlReaderDelegator(reader), verifyObjectName);
  360. }
  361. public override bool IsStartObject(XmlDictionaryReader reader)
  362. {
  363. return IsStartObjectHandleExceptions(new XmlReaderDelegator(reader));
  364. }
  365. internal override object InternalReadObject(XmlReaderDelegator xmlReader, bool verifyObjectName)
  366. {
  367. if (MaxItemsInObjectGraph == 0)
  368. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.ExceededMaxItemsQuota, MaxItemsInObjectGraph)));
  369. // verifyObjectName has no effect in SharedType mode
  370. if (!IsStartElement(xmlReader))
  371. {
  372. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationExceptionWithReaderDetails(SR.GetString(SR.ExpectingElementAtDeserialize, XmlNodeType.Element), xmlReader));
  373. }
  374. XmlObjectSerializerReadContext context = XmlObjectSerializerReadContext.CreateContext(this);
  375. return context.InternalDeserialize(xmlReader, null, null, null);
  376. }
  377. internal override bool InternalIsStartObject(XmlReaderDelegator reader)
  378. {
  379. return IsStartElement(reader);
  380. }
  381. internal DataContract GetDataContract(object obj, ref Hashtable surrogateDataContracts)
  382. {
  383. return GetDataContract(((obj == null) ? Globals.TypeOfObject : obj.GetType()), ref surrogateDataContracts);
  384. }
  385. internal DataContract GetDataContract(Type type, ref Hashtable surrogateDataContracts)
  386. {
  387. return GetDataContract(type.TypeHandle, type, ref surrogateDataContracts);
  388. }
  389. internal DataContract GetDataContract(RuntimeTypeHandle typeHandle, Type type, ref Hashtable surrogateDataContracts)
  390. {
  391. DataContract dataContract = GetDataContractFromSurrogateSelector(surrogateSelector, Context, typeHandle, type, ref surrogateDataContracts);
  392. if (dataContract != null)
  393. return dataContract;
  394. if (cachedDataContract == null)
  395. {
  396. dataContract = DataContract.GetDataContract(typeHandle, type, SerializationMode.SharedType);
  397. cachedDataContract = dataContract;
  398. return dataContract;
  399. }
  400. DataContract currentCachedDataContract = cachedDataContract;
  401. if (currentCachedDataContract.UnderlyingType.TypeHandle.Equals(typeHandle))
  402. return currentCachedDataContract;
  403. return DataContract.GetDataContract(typeHandle, type, SerializationMode.SharedType);
  404. }
  405. [Fx.Tag.SecurityNote(Critical = "Calls the critical methods of ISurrogateSelector", Safe = "Demands for FullTrust")]
  406. [SecuritySafeCritical]
  407. [PermissionSet(SecurityAction.Demand, Unrestricted = true)]
  408. [MethodImpl(MethodImplOptions.NoInlining)]
  409. static ISerializationSurrogate GetSurrogate(Type type, ISurrogateSelector surrogateSelector, StreamingContext context)
  410. {
  411. ISurrogateSelector surrogateSelectorNotUsed;
  412. return surrogateSelector.GetSurrogate(type, context, out surrogateSelectorNotUsed);
  413. }
  414. internal static DataContract GetDataContractFromSurrogateSelector(ISurrogateSelector surrogateSelector, StreamingContext context, RuntimeTypeHandle typeHandle, Type type, ref Hashtable surrogateDataContracts)
  415. {
  416. if (surrogateSelector == null)
  417. return null;
  418. if (type == null)
  419. type = Type.GetTypeFromHandle(typeHandle);
  420. DataContract builtInDataContract = DataContract.GetBuiltInDataContract(type);
  421. if (builtInDataContract != null)
  422. return builtInDataContract;
  423. if (surrogateDataContracts != null)
  424. {
  425. DataContract cachedSurrogateContract = (DataContract)surrogateDataContracts[type];
  426. if (cachedSurrogateContract != null)
  427. return cachedSurrogateContract;
  428. }
  429. DataContract surrogateContract = null;
  430. ISerializationSurrogate surrogate = GetSurrogate(type, surrogateSelector, context);
  431. if (surrogate != null)
  432. surrogateContract = new SurrogateDataContract(type, surrogate);
  433. else if (type.IsArray)
  434. {
  435. Type elementType = type.GetElementType();
  436. DataContract itemContract = GetDataContractFromSurrogateSelector(surrogateSelector, context, elementType.TypeHandle, elementType, ref surrogateDataContracts);
  437. if (itemContract == null)
  438. itemContract = DataContract.GetDataContract(elementType.TypeHandle, elementType, SerializationMode.SharedType);
  439. surrogateContract = new CollectionDataContract(type, itemContract);
  440. }
  441. if (surrogateContract != null)
  442. {
  443. if (surrogateDataContracts == null)
  444. surrogateDataContracts = new Hashtable();
  445. surrogateDataContracts.Add(type, surrogateContract);
  446. return surrogateContract;
  447. }
  448. return null;
  449. }
  450. internal static TypeInformation GetTypeInformation(Type type)
  451. {
  452. TypeInformation typeInformation = null;
  453. object typeInformationObject = typeNameCache[type];
  454. if (typeInformationObject == null)
  455. {
  456. bool hasTypeForwardedFrom;
  457. string assemblyName = DataContract.GetClrAssemblyName(type, out hasTypeForwardedFrom);
  458. typeInformation = new TypeInformation(DataContract.GetClrTypeFullNameUsingTypeForwardedFromAttribute(type), assemblyName, hasTypeForwardedFrom);
  459. lock (typeNameCache)
  460. {
  461. typeNameCache[type] = typeInformation;
  462. }
  463. }
  464. else
  465. {
  466. typeInformation = (TypeInformation)typeInformationObject;
  467. }
  468. return typeInformation;
  469. }
  470. static bool IsAssemblyNameForwardingSafe(string originalAssemblyName, string newAssemblyName)
  471. {
  472. if (originalAssemblyName == newAssemblyName)
  473. {
  474. return true;
  475. }
  476. AssemblyName originalAssembly = new AssemblyName(originalAssemblyName);
  477. AssemblyName newAssembly = new AssemblyName(newAssemblyName);
  478. // mscorlib will get loaded by the runtime regardless of its string casing or its public key token,
  479. // so setting the assembly name to mscorlib is always unsafe
  480. if (string.Equals(newAssembly.Name, Globals.MscorlibAssemblySimpleName, StringComparison.OrdinalIgnoreCase) ||
  481. string.Equals(newAssembly.Name, Globals.MscorlibFileName, StringComparison.OrdinalIgnoreCase))
  482. {
  483. return false;
  484. }
  485. return IsPublicKeyTokenForwardingSafe(originalAssembly.GetPublicKeyToken(), newAssembly.GetPublicKeyToken());
  486. }
  487. static bool IsPublicKeyTokenForwardingSafe(byte[] sourceToken, byte[] destinationToken)
  488. {
  489. if (sourceToken == null || destinationToken == null || sourceToken.Length == 0 || destinationToken.Length == 0 || sourceToken.Length != destinationToken.Length)
  490. {
  491. return false;
  492. }
  493. for (int i = 0; i < sourceToken.Length; i++)
  494. {
  495. if (sourceToken[i] != destinationToken[i])
  496. {
  497. return false;
  498. }
  499. }
  500. return true;
  501. }
  502. }
  503. }