-
Notifications
You must be signed in to change notification settings - Fork 533
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Xamarin.Android.Build.Tasks] use System.Reflection.Metadata in <ResolveAssemblies/> #2612
Merged
jonpryor
merged 2 commits into
dotnet:master
from
jonathanpeppers:resolveassemblies-srm
Jan 16, 2019
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 34 additions & 0 deletions
34
src/Xamarin.Android.Build.Tasks/Utilities/DummyCustomAttributeProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
using System.Reflection.Metadata; | ||
|
||
namespace Xamarin.Android.Tasks | ||
{ | ||
/// <summary> | ||
/// A helper type for System.Reflection.Metadata. Getting the value of custom attribute arguments is a bit convoluted, if you merely want the values. | ||
/// | ||
/// This interface allows usage such as: | ||
/// CustomAttribute attribute = reader.GetCustomAttribute (handle); | ||
/// CustomAttributeValue<object> decoded = attribute.DecodeValue (DummyCustomAttributeProvider.Instance); | ||
/// Or better yet, used via the extension method: | ||
/// CustomAttributeValue<object> decoded = attribute.GetCustomAttributeArguments (); | ||
/// </summary> | ||
public class DummyCustomAttributeProvider : ICustomAttributeTypeProvider<object> | ||
{ | ||
public static readonly DummyCustomAttributeProvider Instance = new DummyCustomAttributeProvider (); | ||
|
||
public object GetPrimitiveType (PrimitiveTypeCode typeCode) => null; | ||
|
||
public object GetSystemType () => null; | ||
|
||
public object GetSZArrayType (object elementType) => null; | ||
|
||
public object GetTypeFromDefinition (MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind) => null; | ||
|
||
public object GetTypeFromReference (MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind) => null; | ||
|
||
public object GetTypeFromSerializedName (string name) => null; | ||
|
||
public PrimitiveTypeCode GetUnderlyingEnumType (object type) => default (PrimitiveTypeCode); | ||
|
||
public bool IsSystemType (object type) => false; | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
src/Xamarin.Android.Build.Tasks/Utilities/MetadataExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
using System.Reflection.Metadata; | ||
|
||
namespace Xamarin.Android.Tasks | ||
{ | ||
public static class MetadataExtensions | ||
{ | ||
public static string GetCustomAttributeFullName (this MetadataReader reader, CustomAttribute attribute) | ||
{ | ||
if (attribute.Constructor.Kind == HandleKind.MemberReference) { | ||
var ctor = reader.GetMemberReference ((MemberReferenceHandle)attribute.Constructor); | ||
var type = reader.GetTypeReference ((TypeReferenceHandle)ctor.Parent); | ||
return reader.GetString (type.Namespace) + "." + reader.GetString (type.Name); | ||
} else if (attribute.Constructor.Kind == HandleKind.MethodDefinition) { | ||
var ctor = reader.GetMethodDefinition ((MethodDefinitionHandle)attribute.Constructor); | ||
var type = reader.GetTypeDefinition (ctor.GetDeclaringType ()); | ||
return reader.GetString (type.Namespace) + "." + reader.GetString (type.Name); | ||
} | ||
return null; | ||
} | ||
|
||
public static CustomAttributeValue<object> GetCustomAttributeArguments (this CustomAttribute attribute) | ||
{ | ||
return attribute.DecodeValue (DummyCustomAttributeProvider.Instance); | ||
} | ||
} | ||
} |
60 changes: 60 additions & 0 deletions
60
src/Xamarin.Android.Build.Tasks/Utilities/MetadataResolver.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Reflection.Metadata; | ||
using System.Reflection.PortableExecutable; | ||
|
||
namespace Xamarin.Android.Tasks | ||
{ | ||
/// <summary> | ||
/// A replacement for DirectoryAssemblyResolver, using System.Reflection.Metadata | ||
/// </summary> | ||
public class MetadataResolver : IDisposable | ||
{ | ||
readonly Dictionary<string, PEReader> cache = new Dictionary<string, PEReader> (); | ||
readonly List<string> searchDirectories = new List<string> (); | ||
|
||
public MetadataReader GetAssemblyReader (string assemblyName) | ||
{ | ||
var key = Path.GetFileNameWithoutExtension (assemblyName); | ||
if (!cache.TryGetValue (key, out PEReader reader)) { | ||
var assemblyPath = Resolve (assemblyName); | ||
cache.Add (key, reader = new PEReader (File.OpenRead (assemblyPath))); | ||
} | ||
return reader.GetMetadataReader (); | ||
} | ||
|
||
public void AddSearchDirectory (string directory) | ||
{ | ||
directory = Path.GetFullPath (directory); | ||
if (!searchDirectories.Contains (directory)) | ||
searchDirectories.Add (directory); | ||
} | ||
|
||
public string Resolve (string assemblyName) | ||
{ | ||
string assemblyPath = assemblyName; | ||
if (!assemblyPath.EndsWith (".dll", StringComparison.OrdinalIgnoreCase)) { | ||
assemblyPath += ".dll"; | ||
} | ||
if (File.Exists (assemblyPath)) { | ||
return assemblyPath; | ||
} | ||
foreach (var dir in searchDirectories) { | ||
var path = Path.Combine (dir, assemblyPath); | ||
if (File.Exists (path)) | ||
return path; | ||
} | ||
|
||
throw new FileNotFoundException ($"Could not load assembly '{assemblyName}'.", assemblyName); | ||
} | ||
|
||
public void Dispose () | ||
{ | ||
foreach (var provider in cache.Values) { | ||
provider.Dispose (); | ||
} | ||
cache.Clear (); | ||
} | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this also support
.exe
suffixes?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since e390702 we dropped support for referencing exe's at the MSBuild level. I didn't add support for it here, but if there is some scenario you think we'll hit, I can add it.
Offhand I can't think of a case where a
.dll
would reference a random.exe
?