Skip to content

Commit

Permalink
Use Assembly.Load as first option to load TempAssembly. (#52429)
Browse files Browse the repository at this point in the history
* Use Assembly.Load as first option to load TempAssembly.
  • Loading branch information
StephenMolloy authored May 20, 2021
1 parent 80c81b3 commit e2f5c11
Showing 1 changed file with 48 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ internal void InitAssemblyMethods(XmlMapping[] xmlMappings)
/// </devdoc>
// SxS: This method does not take any resource name and does not expose any resources to the caller.
// It's OK to suppress the SxS warning.
[RequiresUnreferencedCode("calls LoadFile")]
[RequiresUnreferencedCode("calls LoadFrom")]
[UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file",
Justification = "Annotating this as dangerous will make the core of the serializer to be marked as not safe, instead " +
"this pattern is only dangerous if using sgen only. See https://github.com/dotnet/runtime/issues/50820")]
Expand All @@ -161,39 +161,20 @@ internal void InitAssemblyMethods(XmlMapping[] xmlMappings)
name.CodeBase = null;
name.CultureInfo = CultureInfo.InvariantCulture;

string? serializerPath = null;

try
{
if (!string.IsNullOrEmpty(type.Assembly.Location))
{
serializerPath = Path.Combine(Path.GetDirectoryName(type.Assembly.Location)!, serializerName + ".dll");
}

if ((string.IsNullOrEmpty(serializerPath) || !File.Exists(serializerPath)) && !string.IsNullOrEmpty(Assembly.GetEntryAssembly()?.Location))
{
serializerPath = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly()!.Location)!, serializerName + ".dll");
}

if (!string.IsNullOrEmpty(serializerPath))
{
serializer = Assembly.LoadFile(serializerPath);
}
serializer = Assembly.Load(name);
}
catch (Exception e)
{
if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException)
if (e is OutOfMemoryException)
{
throw;
}
byte[]? token = name.GetPublicKeyToken();
if (token != null && token.Length > 0)
{
// the parent assembly was signed, so do not try to LoadWithPartialName
return null;
}
}

serializer ??= LoadAssemblyByPath(type, serializerName);

if (serializer == null)
{
if (XmlSerializer.Mode == SerializationMode.PreGenOnly)
Expand All @@ -220,9 +201,7 @@ internal void InitAssemblyMethods(XmlMapping[] xmlMappings)
if (assemblyAttribute.AssemblyName != null)
{
serializerName = assemblyAttribute.AssemblyName;
#pragma warning disable 618
serializer = Assembly.LoadWithPartialName(serializerName);
#pragma warning restore 618
serializer = Assembly.Load(serializerName); // LoadWithPartialName just does this in .Net Core; changing the obsolete call.
}
else if (assemblyAttribute.CodeBase != null && assemblyAttribute.CodeBase.Length > 0)
{
Expand All @@ -247,6 +226,48 @@ internal void InitAssemblyMethods(XmlMapping[] xmlMappings)
return null;
}

[RequiresUnreferencedCode("calls LoadFile")]
[UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file",
Justification = "Annotating this as dangerous will make the core of the serializer to be marked as not safe, instead " +
"this pattern is only dangerous if using sgen only. See https://github.com/dotnet/runtime/issues/50820")]
private static Assembly? LoadAssemblyByPath(Type type, string assemblyName)
{
Assembly? assembly = null;
string? path = null;

try
{
if (!string.IsNullOrEmpty(type.Assembly.Location))
{
path = Path.Combine(Path.GetDirectoryName(type.Assembly.Location)!, assemblyName + ".dll");
}

if ((string.IsNullOrEmpty(path) || !File.Exists(path)) && !string.IsNullOrEmpty(Assembly.GetEntryAssembly()?.Location))
{
path = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly()!.Location)!, assemblyName + ".dll");
}

if ((string.IsNullOrEmpty(path) || !File.Exists(path)) && !string.IsNullOrEmpty(AppContext.BaseDirectory))
{
path = Path.Combine(Path.GetDirectoryName(AppContext.BaseDirectory)!, assemblyName + ".dll");
}

if (!string.IsNullOrEmpty(path))
{
assembly = Assembly.LoadFile(path);
}
}
catch (Exception e)
{
if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException)
{
throw;
}
}

return assembly;
}

private static bool IsSerializerVersionMatch(Assembly serializer, Type type, string? defaultNamespace)
{
if (serializer == null)
Expand Down

0 comments on commit e2f5c11

Please sign in to comment.