Reputation: 56
I want to compile some classes at runtime, but to do so I need to reference some assemblies like System.Linq.dll or System.Collections.dll.
The problem is that I can't use MetadataReference.CreateFromFile
because Assembly.Location
only returns the assembly name and not a file path when the solution is built in Release mode.
Is there any alternative?
I've already tried some solutions found online but none of them worked, such as:
var methodInfo = assembly.GetType().GetMethod("GetRawBytes", BindingFlags.Instance | BindingFlags.NonPublic);
byte[] assemblyBytes = (byte[])methodInfo.Invoke(assembly, null);
var reference = MetadataReference.CreateFromImage(assemblyBytes);
The problem with this one is that GetRawBytes
no longer exists in newer .NET versions github.com/dotnet/runtime/issues/28132#issue-558436811
var hash = new Hash(assembly);
var dllAsArray = (byte[])hash.GetType().GetMethod("GetRawData", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(hash, new object[0]);
var reference = MetadataReference.CreateFromImage(dllAsArray);
The problem with this one is that Hash()
only works on Windows.
var formatter = new BinaryFormatter();
var ms = new MemoryStream();
formatter.Serialize(ms, assembly);
var reference = MetadataReference.CreateFromImage(ms.GetBuffer());
The problem with this one is that BinaryFormatter
is obsolete and raises an error in compile time.
I also found this repo on github which seems to have the solution to work on Android, but when trying to reproduce this in my app I get a NotImplementedException
calling the TryGetRawMetadata()
extension method.
Upvotes: 0
Views: 90
Reputation: 56
I found a workaround. It's not the best solution, but it's working.
First I added a post-build event to copy the resulting DLLs to a project directory:
xcopy "$(ProjectDir)obj\$(Configuration)\$(TargetFramework)\android\assets\*.dll" "$(ProjectDir)Resources\Libraries" /Y
I then defined the required DLLs as Maui Asset in the .csproj file. For example:
<ItemGroup>
<None Remove="Resources\Libraries\System.Linq.dll" />
</ItemGroup>
<ItemGroup>
<MauiAsset Include="Resources\Libraries\System.Linq.dll" />
</ItemGroup>
Finally, I'm loading the reference with the following:
using var stream = await FileSystem.OpenAppPackageFileAsync("Resources/Libraries/System.Linq.dll");
using var ms = new MemoryStream();
stream.CopyTo(ms);
var reference = MetadataReference.CreateFromImage(ms.GetBuffer());
Upvotes: 0