600 lines
24 KiB
C#
600 lines
24 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.IO;
|
|
using System.Reflection;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Runtime.Serialization.Formatters;
|
|
using System.Xml;
|
|
using IFormatter = System.Runtime.Serialization.IFormatter;
|
|
using ISerializationSurrogate = System.Runtime.Serialization.ISerializationSurrogate;
|
|
using ISurrogateSelector = System.Runtime.Serialization.ISurrogateSelector;
|
|
using SerializationBinder = System.Runtime.Serialization.SerializationBinder;
|
|
using SerializationInfo = System.Runtime.Serialization.SerializationInfo;
|
|
using StreamingContext = System.Runtime.Serialization.StreamingContext;
|
|
using StreamingContextStates = System.Runtime.Serialization.StreamingContextStates;
|
|
|
|
namespace Compat.Runtime.Serialization
|
|
{
|
|
public sealed class NetDataContractSerializer : XmlObjectSerializer, IFormatter
|
|
{
|
|
private XmlDictionaryString rootName;
|
|
private XmlDictionaryString rootNamespace;
|
|
private StreamingContext context;
|
|
private SerializationBinder binder;
|
|
private ISurrogateSelector surrogateSelector;
|
|
private int maxItemsInObjectGraph;
|
|
private bool ignoreExtensionDataObject;
|
|
private FormatterAssemblyStyle assemblyFormat;
|
|
private DataContract cachedDataContract;
|
|
private static readonly Hashtable typeNameCache = new Hashtable();
|
|
|
|
public NetDataContractSerializer()
|
|
: this(new StreamingContext(StreamingContextStates.All))
|
|
{
|
|
}
|
|
|
|
public NetDataContractSerializer(StreamingContext context)
|
|
: this(context, int.MaxValue, false, FormatterAssemblyStyle.Full, null)
|
|
{
|
|
}
|
|
|
|
public NetDataContractSerializer(StreamingContext context,
|
|
int maxItemsInObjectGraph,
|
|
bool ignoreExtensionDataObject,
|
|
FormatterAssemblyStyle assemblyFormat,
|
|
ISurrogateSelector surrogateSelector)
|
|
{
|
|
Initialize(context, maxItemsInObjectGraph, ignoreExtensionDataObject, assemblyFormat, surrogateSelector);
|
|
}
|
|
|
|
public NetDataContractSerializer(string rootName, string rootNamespace)
|
|
: this(rootName, rootNamespace, new StreamingContext(StreamingContextStates.All), int.MaxValue, false, FormatterAssemblyStyle.Full, null)
|
|
{
|
|
}
|
|
|
|
public NetDataContractSerializer(string rootName, string rootNamespace,
|
|
StreamingContext context,
|
|
int maxItemsInObjectGraph,
|
|
bool ignoreExtensionDataObject,
|
|
FormatterAssemblyStyle assemblyFormat,
|
|
ISurrogateSelector surrogateSelector)
|
|
{
|
|
XmlDictionary dictionary = new XmlDictionary(2);
|
|
Initialize(dictionary.Add(rootName), dictionary.Add(DataContract.GetNamespace(rootNamespace)), context, maxItemsInObjectGraph, ignoreExtensionDataObject, assemblyFormat, surrogateSelector);
|
|
}
|
|
|
|
public NetDataContractSerializer(XmlDictionaryString rootName, XmlDictionaryString rootNamespace)
|
|
: this(rootName, rootNamespace, new StreamingContext(StreamingContextStates.All), int.MaxValue, false, FormatterAssemblyStyle.Full, null)
|
|
{
|
|
}
|
|
|
|
public NetDataContractSerializer(XmlDictionaryString rootName, XmlDictionaryString rootNamespace,
|
|
StreamingContext context,
|
|
int maxItemsInObjectGraph,
|
|
bool ignoreExtensionDataObject,
|
|
FormatterAssemblyStyle assemblyFormat,
|
|
ISurrogateSelector surrogateSelector)
|
|
{
|
|
Initialize(rootName, rootNamespace, context, maxItemsInObjectGraph, ignoreExtensionDataObject, assemblyFormat, surrogateSelector);
|
|
}
|
|
|
|
private void Initialize(StreamingContext context,
|
|
int maxItemsInObjectGraph,
|
|
bool ignoreExtensionDataObject,
|
|
FormatterAssemblyStyle assemblyFormat,
|
|
ISurrogateSelector surrogateSelector)
|
|
{
|
|
this.context = context;
|
|
if (maxItemsInObjectGraph < 0)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(maxItemsInObjectGraph), SR.ValueMustBeNonNegative));
|
|
}
|
|
|
|
this.maxItemsInObjectGraph = maxItemsInObjectGraph;
|
|
this.ignoreExtensionDataObject = ignoreExtensionDataObject;
|
|
this.surrogateSelector = surrogateSelector;
|
|
AssemblyFormat = assemblyFormat;
|
|
}
|
|
|
|
private void Initialize(XmlDictionaryString rootName, XmlDictionaryString rootNamespace,
|
|
StreamingContext context,
|
|
int maxItemsInObjectGraph,
|
|
bool ignoreExtensionDataObject,
|
|
FormatterAssemblyStyle assemblyFormat,
|
|
ISurrogateSelector surrogateSelector)
|
|
{
|
|
Initialize(context, maxItemsInObjectGraph, ignoreExtensionDataObject, assemblyFormat, surrogateSelector);
|
|
this.rootName = rootName;
|
|
this.rootNamespace = rootNamespace;
|
|
}
|
|
|
|
public StreamingContext Context
|
|
{
|
|
get => context;
|
|
set => context = value;
|
|
}
|
|
|
|
public SerializationBinder Binder
|
|
{
|
|
get => binder;
|
|
set => binder = value;
|
|
}
|
|
|
|
public ISurrogateSelector SurrogateSelector
|
|
{
|
|
get => surrogateSelector;
|
|
set => surrogateSelector = value;
|
|
}
|
|
|
|
public FormatterAssemblyStyle AssemblyFormat
|
|
{
|
|
get => assemblyFormat;
|
|
set
|
|
{
|
|
if (value != FormatterAssemblyStyle.Full && value != FormatterAssemblyStyle.Simple)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.Format(SR.InvalidAssemblyFormat, value)));
|
|
}
|
|
|
|
assemblyFormat = value;
|
|
}
|
|
}
|
|
|
|
public int MaxItemsInObjectGraph => maxItemsInObjectGraph;
|
|
|
|
public bool IgnoreExtensionDataObject => ignoreExtensionDataObject;
|
|
|
|
public void Serialize(Stream stream, object graph)
|
|
{
|
|
base.WriteObject(stream, graph);
|
|
}
|
|
|
|
public object Deserialize(Stream stream)
|
|
{
|
|
return base.ReadObject(stream);
|
|
}
|
|
|
|
public object Deserialize(XmlReader reader)
|
|
{
|
|
return base.ReadObject(reader);
|
|
}
|
|
|
|
internal override void InternalWriteObject(XmlWriterDelegator writer, object graph)
|
|
{
|
|
Hashtable surrogateDataContracts = null;
|
|
DataContract contract = GetDataContract(graph, ref surrogateDataContracts);
|
|
|
|
InternalWriteStartObject(writer, graph, contract);
|
|
InternalWriteObjectContent(writer, graph, contract, surrogateDataContracts);
|
|
InternalWriteEndObject(writer);
|
|
}
|
|
|
|
public override void WriteObject(XmlWriter writer, object graph)
|
|
{
|
|
WriteObjectHandleExceptions(new XmlWriterDelegator(writer), graph);
|
|
}
|
|
|
|
public override void WriteStartObject(XmlWriter writer, object graph)
|
|
{
|
|
WriteStartObjectHandleExceptions(new XmlWriterDelegator(writer), graph);
|
|
}
|
|
|
|
public override void WriteObjectContent(XmlWriter writer, object graph)
|
|
{
|
|
WriteObjectContentHandleExceptions(new XmlWriterDelegator(writer), graph);
|
|
}
|
|
|
|
public override void WriteEndObject(XmlWriter writer)
|
|
{
|
|
WriteEndObjectHandleExceptions(new XmlWriterDelegator(writer));
|
|
}
|
|
|
|
public override void WriteStartObject(XmlDictionaryWriter writer, object graph)
|
|
{
|
|
WriteStartObjectHandleExceptions(new XmlWriterDelegator(writer), graph);
|
|
}
|
|
|
|
internal override void InternalWriteStartObject(XmlWriterDelegator writer, object graph)
|
|
{
|
|
Hashtable surrogateDataContracts = null;
|
|
DataContract contract = GetDataContract(graph, ref surrogateDataContracts);
|
|
InternalWriteStartObject(writer, graph, contract);
|
|
}
|
|
|
|
private void InternalWriteStartObject(XmlWriterDelegator writer, object graph, DataContract contract)
|
|
{
|
|
WriteRootElement(writer, contract, rootName, rootNamespace, CheckIfNeedsContractNsAtRoot(rootName, rootNamespace, contract));
|
|
}
|
|
|
|
public override void WriteObjectContent(XmlDictionaryWriter writer, object graph)
|
|
{
|
|
WriteObjectContentHandleExceptions(new XmlWriterDelegator(writer), graph);
|
|
}
|
|
|
|
internal override void InternalWriteObjectContent(XmlWriterDelegator writer, object graph)
|
|
{
|
|
Hashtable surrogateDataContracts = null;
|
|
DataContract contract = GetDataContract(graph, ref surrogateDataContracts);
|
|
InternalWriteObjectContent(writer, graph, contract, surrogateDataContracts);
|
|
}
|
|
|
|
private void InternalWriteObjectContent(XmlWriterDelegator writer, object graph, DataContract contract, Hashtable surrogateDataContracts)
|
|
{
|
|
if (MaxItemsInObjectGraph == 0)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.ExceededMaxItemsQuota, MaxItemsInObjectGraph)));
|
|
}
|
|
|
|
if (IsRootXmlAny(rootName, contract))
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.IsAnyNotSupportedByNetDataContractSerializer, contract.UnderlyingType)));
|
|
}
|
|
else if (graph == null)
|
|
{
|
|
WriteNull(writer);
|
|
}
|
|
else
|
|
{
|
|
Type graphType = graph.GetType();
|
|
if (contract.UnderlyingType != graphType)
|
|
{
|
|
contract = GetDataContract(graph, ref surrogateDataContracts);
|
|
}
|
|
|
|
XmlObjectSerializerWriteContext context = null;
|
|
if (contract.CanContainReferences)
|
|
{
|
|
context = XmlObjectSerializerWriteContext.CreateContext(this, surrogateDataContracts);
|
|
context.HandleGraphAtTopLevel(writer, graph, contract);
|
|
}
|
|
|
|
WriteClrTypeInfo(writer, contract, binder);
|
|
contract.WriteXmlValue(writer, graph, context);
|
|
}
|
|
}
|
|
|
|
// Update the overloads whenever you are changing this method
|
|
internal static void WriteClrTypeInfo(XmlWriterDelegator writer, DataContract dataContract, SerializationBinder binder)
|
|
{
|
|
if (!dataContract.IsISerializable && !(dataContract is SurrogateDataContract))
|
|
{
|
|
TypeInformation typeInformation = null;
|
|
Type clrType = dataContract.OriginalUnderlyingType;
|
|
string clrTypeName = null;
|
|
string clrAssemblyName = null;
|
|
|
|
if (binder != null)
|
|
{
|
|
binder.BindToName(clrType, out clrAssemblyName, out clrTypeName);
|
|
}
|
|
|
|
if (clrTypeName == null)
|
|
{
|
|
typeInformation = NetDataContractSerializer.GetTypeInformation(clrType);
|
|
clrTypeName = typeInformation.FullTypeName;
|
|
}
|
|
|
|
if (clrAssemblyName == null)
|
|
{
|
|
clrAssemblyName = (typeInformation == null) ?
|
|
NetDataContractSerializer.GetTypeInformation(clrType).AssemblyString :
|
|
typeInformation.AssemblyString;
|
|
|
|
// Throw in the [TypeForwardedFrom] case to prevent a partially trusted assembly from forwarding itself to an assembly with higher privileges
|
|
if (!UnsafeTypeForwardingEnabled && !clrType.Assembly.IsFullyTrusted && !IsAssemblyNameForwardingSafe(clrType.Assembly.FullName, clrAssemblyName))
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.TypeCannotBeForwardedFrom, DataContract.GetClrTypeFullName(clrType), clrType.Assembly.FullName, clrAssemblyName)));
|
|
}
|
|
}
|
|
|
|
WriteClrTypeInfo(writer, clrTypeName, clrAssemblyName);
|
|
}
|
|
}
|
|
|
|
public static bool UnsafeTypeForwardingEnabled => false;
|
|
|
|
// Update the overloads whenever you are changing this method
|
|
internal static void WriteClrTypeInfo(XmlWriterDelegator writer, Type dataContractType, SerializationBinder binder, string defaultClrTypeName, string defaultClrAssemblyName)
|
|
{
|
|
string clrTypeName = null;
|
|
string clrAssemblyName = null;
|
|
|
|
if (binder != null)
|
|
{
|
|
binder.BindToName(dataContractType, out clrAssemblyName, out clrTypeName);
|
|
}
|
|
|
|
if (clrTypeName == null)
|
|
{
|
|
clrTypeName = defaultClrTypeName;
|
|
}
|
|
|
|
if (clrAssemblyName == null)
|
|
{
|
|
clrAssemblyName = defaultClrAssemblyName;
|
|
}
|
|
|
|
WriteClrTypeInfo(writer, clrTypeName, clrAssemblyName);
|
|
}
|
|
|
|
// Update the overloads whenever you are changing this method
|
|
internal static void WriteClrTypeInfo(
|
|
XmlWriterDelegator writer,
|
|
Type dataContractType,
|
|
SerializationBinder binder,
|
|
SerializationInfo serInfo)
|
|
{
|
|
TypeInformation typeInformation = null;
|
|
string clrTypeName = null;
|
|
string clrAssemblyName = null;
|
|
|
|
if (binder != null)
|
|
{
|
|
binder.BindToName(dataContractType, out clrAssemblyName, out clrTypeName);
|
|
}
|
|
|
|
if (clrTypeName == null)
|
|
{
|
|
if (serInfo.IsFullTypeNameSetExplicit)
|
|
{
|
|
clrTypeName = serInfo.FullTypeName;
|
|
}
|
|
else
|
|
{
|
|
typeInformation = NetDataContractSerializer.GetTypeInformation(serInfo.ObjectType);
|
|
clrTypeName = typeInformation.FullTypeName;
|
|
}
|
|
}
|
|
|
|
if (clrAssemblyName == null)
|
|
{
|
|
if (serInfo.IsAssemblyNameSetExplicit)
|
|
{
|
|
clrAssemblyName = serInfo.AssemblyName;
|
|
}
|
|
else
|
|
{
|
|
clrAssemblyName = (typeInformation == null) ?
|
|
NetDataContractSerializer.GetTypeInformation(serInfo.ObjectType).AssemblyString :
|
|
typeInformation.AssemblyString;
|
|
}
|
|
}
|
|
|
|
WriteClrTypeInfo(writer, clrTypeName, clrAssemblyName);
|
|
}
|
|
|
|
private static void WriteClrTypeInfo(XmlWriterDelegator writer, string clrTypeName, string clrAssemblyName)
|
|
{
|
|
if (clrTypeName != null)
|
|
{
|
|
writer.WriteAttributeString(Globals.SerPrefix, DictionaryGlobals.ClrTypeLocalName, DictionaryGlobals.SerializationNamespace, DataContract.GetClrTypeString(clrTypeName));
|
|
}
|
|
|
|
if (clrAssemblyName != null)
|
|
{
|
|
writer.WriteAttributeString(Globals.SerPrefix, DictionaryGlobals.ClrAssemblyLocalName, DictionaryGlobals.SerializationNamespace, DataContract.GetClrTypeString(clrAssemblyName));
|
|
}
|
|
}
|
|
|
|
public override void WriteEndObject(XmlDictionaryWriter writer)
|
|
{
|
|
WriteEndObjectHandleExceptions(new XmlWriterDelegator(writer));
|
|
}
|
|
|
|
internal override void InternalWriteEndObject(XmlWriterDelegator writer)
|
|
{
|
|
writer.WriteEndElement();
|
|
}
|
|
|
|
public override object ReadObject(XmlReader reader)
|
|
{
|
|
return ReadObjectHandleExceptions(new XmlReaderDelegator(reader), true /*verifyObjectName*/);
|
|
}
|
|
|
|
public override object ReadObject(XmlReader reader, bool verifyObjectName)
|
|
{
|
|
return ReadObjectHandleExceptions(new XmlReaderDelegator(reader), verifyObjectName);
|
|
}
|
|
|
|
public override bool IsStartObject(XmlReader reader)
|
|
{
|
|
return IsStartObjectHandleExceptions(new XmlReaderDelegator(reader));
|
|
}
|
|
|
|
public override object ReadObject(XmlDictionaryReader reader, bool verifyObjectName)
|
|
{
|
|
return ReadObjectHandleExceptions(new XmlReaderDelegator(reader), verifyObjectName);
|
|
}
|
|
|
|
public override bool IsStartObject(XmlDictionaryReader reader)
|
|
{
|
|
return IsStartObjectHandleExceptions(new XmlReaderDelegator(reader));
|
|
}
|
|
|
|
internal override object InternalReadObject(XmlReaderDelegator xmlReader, bool verifyObjectName)
|
|
{
|
|
if (MaxItemsInObjectGraph == 0)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.ExceededMaxItemsQuota, MaxItemsInObjectGraph)));
|
|
}
|
|
|
|
// verifyObjectName has no effect in SharedType mode
|
|
if (!IsStartElement(xmlReader))
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationExceptionWithReaderDetails(SR.Format(SR.ExpectingElementAtDeserialize, XmlNodeType.Element), xmlReader));
|
|
}
|
|
|
|
XmlObjectSerializerReadContext context = XmlObjectSerializerReadContext.CreateContext(this);
|
|
return context.InternalDeserialize(xmlReader, null, null, null);
|
|
}
|
|
|
|
internal override bool InternalIsStartObject(XmlReaderDelegator reader)
|
|
{
|
|
return IsStartElement(reader);
|
|
}
|
|
|
|
internal DataContract GetDataContract(object obj, ref Hashtable surrogateDataContracts)
|
|
{
|
|
return GetDataContract(((obj == null) ? Globals.TypeOfObject : obj.GetType()), ref surrogateDataContracts);
|
|
}
|
|
|
|
internal DataContract GetDataContract(Type type, ref Hashtable surrogateDataContracts)
|
|
{
|
|
return GetDataContract(type.TypeHandle, type, ref surrogateDataContracts);
|
|
}
|
|
|
|
internal DataContract GetDataContract(RuntimeTypeHandle typeHandle, Type type, ref Hashtable surrogateDataContracts)
|
|
{
|
|
DataContract dataContract = GetDataContractFromSurrogateSelector(surrogateSelector, Context, typeHandle, type, ref surrogateDataContracts);
|
|
if (dataContract != null)
|
|
{
|
|
return dataContract;
|
|
}
|
|
|
|
if (cachedDataContract == null)
|
|
{
|
|
dataContract = DataContract.GetDataContract(typeHandle, type, SerializationMode.SharedType);
|
|
cachedDataContract = dataContract;
|
|
return dataContract;
|
|
}
|
|
|
|
DataContract currentCachedDataContract = cachedDataContract;
|
|
if (currentCachedDataContract.UnderlyingType.TypeHandle.Equals(typeHandle))
|
|
{
|
|
return currentCachedDataContract;
|
|
}
|
|
|
|
return DataContract.GetDataContract(typeHandle, type, SerializationMode.SharedType);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
|
private static ISerializationSurrogate GetSurrogate(
|
|
Type type,
|
|
ISurrogateSelector surrogateSelector,
|
|
StreamingContext context)
|
|
{
|
|
return surrogateSelector.GetSurrogate(type, context, out ISurrogateSelector surrogateSelectorNotUsed);
|
|
}
|
|
|
|
internal static DataContract GetDataContractFromSurrogateSelector(
|
|
ISurrogateSelector surrogateSelector,
|
|
StreamingContext context,
|
|
RuntimeTypeHandle typeHandle,
|
|
Type type,
|
|
ref Hashtable surrogateDataContracts)
|
|
{
|
|
if (surrogateSelector == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if (type == null)
|
|
{
|
|
type = Type.GetTypeFromHandle(typeHandle);
|
|
}
|
|
|
|
DataContract builtInDataContract = DataContract.GetBuiltInDataContract(type);
|
|
if (builtInDataContract != null)
|
|
{
|
|
return builtInDataContract;
|
|
}
|
|
|
|
if (surrogateDataContracts != null)
|
|
{
|
|
DataContract cachedSurrogateContract = (DataContract)surrogateDataContracts[type];
|
|
if (cachedSurrogateContract != null)
|
|
{
|
|
return cachedSurrogateContract;
|
|
}
|
|
}
|
|
DataContract surrogateContract = null;
|
|
ISerializationSurrogate surrogate = GetSurrogate(type, surrogateSelector, context);
|
|
if (surrogate != null)
|
|
{
|
|
surrogateContract = new SurrogateDataContract(type, surrogate);
|
|
}
|
|
else if (type.IsArray)
|
|
{
|
|
Type elementType = type.GetElementType();
|
|
DataContract itemContract = GetDataContractFromSurrogateSelector(surrogateSelector, context, elementType.TypeHandle, elementType, ref surrogateDataContracts);
|
|
if (itemContract == null)
|
|
{
|
|
itemContract = DataContract.GetDataContract(elementType.TypeHandle, elementType, SerializationMode.SharedType);
|
|
}
|
|
|
|
surrogateContract = new CollectionDataContract(type, itemContract);
|
|
}
|
|
if (surrogateContract != null)
|
|
{
|
|
if (surrogateDataContracts == null)
|
|
{
|
|
surrogateDataContracts = new Hashtable();
|
|
}
|
|
|
|
surrogateDataContracts.Add(type, surrogateContract);
|
|
return surrogateContract;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
|
|
internal static TypeInformation GetTypeInformation(Type type)
|
|
{
|
|
TypeInformation typeInformation = null;
|
|
object typeInformationObject = typeNameCache[type];
|
|
if (typeInformationObject == null)
|
|
{
|
|
string assemblyName = DataContract.GetClrAssemblyName(type, out bool hasTypeForwardedFrom);
|
|
typeInformation = new TypeInformation(DataContract.GetClrTypeFullNameUsingTypeForwardedFromAttribute(type), assemblyName, hasTypeForwardedFrom);
|
|
lock (typeNameCache)
|
|
{
|
|
typeNameCache[type] = typeInformation;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
typeInformation = (TypeInformation)typeInformationObject;
|
|
}
|
|
return typeInformation;
|
|
}
|
|
|
|
private static bool IsAssemblyNameForwardingSafe(string originalAssemblyName, string newAssemblyName)
|
|
{
|
|
if (originalAssemblyName == newAssemblyName)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
AssemblyName originalAssembly = new AssemblyName(originalAssemblyName);
|
|
AssemblyName newAssembly = new AssemblyName(newAssemblyName);
|
|
|
|
// mscorlib will get loaded by the runtime regardless of its string casing or its public key token,
|
|
// so setting the assembly name to mscorlib is always unsafe
|
|
if (string.Equals(newAssembly.Name, Globals.MscorlibAssemblySimpleName, StringComparison.OrdinalIgnoreCase) ||
|
|
string.Equals(newAssembly.Name, Globals.MscorlibFileName, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return IsPublicKeyTokenForwardingSafe(originalAssembly.GetPublicKeyToken(), newAssembly.GetPublicKeyToken());
|
|
}
|
|
|
|
private static bool IsPublicKeyTokenForwardingSafe(byte[] sourceToken, byte[] destinationToken)
|
|
{
|
|
if (sourceToken == null || destinationToken == null || sourceToken.Length == 0 || destinationToken.Length == 0 || sourceToken.Length != destinationToken.Length)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
for (int i = 0; i < sourceToken.Length; i++)
|
|
{
|
|
if (sourceToken[i] != destinationToken[i])
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
}
|