You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MAUI Android Debug与Release运行时目录差异致反射问题

MAUI Android Release模式下无法获取程序集的解决方案

问题背景

在MAUI应用中需通过反射获取程序集,使用以下代码实现:

var runtimeAssemblies = new HashSet<string>(Directory.GetFiles(RuntimeEnvironment.GetRuntimeDirectory(), "*.dll"));

该代码在Windows平台的Debug/Release模式下均正常运行,但在Android模拟器的Release模式下失效。经排查:

  • Debug模式下,RuntimeEnvironment.GetRuntimeDirectory()返回/data/data/com.compagnyname.myprojectname/files/.__override__,路径下存在所需DLL文件
  • Release模式下,返回路径为/data/user/0/com.compagnyname.myprojectname,该路径下无任何DLL文件,推测程序集已被嵌入打包到APK中,导致MetadataLoadContext无法通过文件路径解析程序集

核心原因

MAUI Android在Release模式下默认启用程序集嵌入优化,所有程序集会被打包为APK的嵌入资源,而非解压到文件系统目录。Debug模式为了调试便利性,会将DLL文件解压到指定目录,因此可以通过目录扫描读取。

解决方案

方案1:通过应用已加载程序集集合获取(推荐)

直接从当前应用的已加载程序集中获取,无需依赖文件系统:

// 获取所有非动态加载的程序集
var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies()
    .Where(assembly => !assembly.IsDynamic)
    .ToList();

如果需要配合MetadataLoadContext使用(需读取程序集元数据),可以将程序集转为字节流加载:

var assemblyBytesList = new List<byte[]>();
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies().Where(a => !a.IsDynamic))
{
    using var memoryStream = new MemoryStream();
    // 从嵌入资源中读取程序集字节流
    var resourceStream = assembly.GetManifestResourceStream($"{assembly.GetName().Name}.dll");
    resourceStream?.CopyTo(memoryStream);
    if (memoryStream.Length > 0)
    {
        assemblyBytesList.Add(memoryStream.ToArray());
    }
}

// 自定义元数据加载上下文的程序集解析器
public class EmbeddedAssemblyResolver : MetadataAssemblyResolver
{
    private readonly List<byte[]> _assemblyBytes;

    public EmbeddedAssemblyResolver(List<byte[]> assemblyBytes)
    {
        _assemblyBytes = assemblyBytes;
    }

    public override Assembly Resolve(MetadataLoadContext context, AssemblyName assemblyName)
    {
        // 匹配目标程序集并加载
        var targetBytes = _assemblyBytes.FirstOrDefault(bytes => 
            AssemblyName.GetAssemblyName(new MemoryStream(bytes)).Name == assemblyName.Name);
        return targetBytes != null ? context.LoadFromStream(new MemoryStream(targetBytes)) : null;
    }
}

// 使用MetadataLoadContext进行反射操作
using var metadataContext = new MetadataLoadContext(new EmbeddedAssemblyResolver(assemblyBytesList));
// 示例:加载指定类型
var targetType = metadataContext.LoadFromAssemblyName("YourAssemblyName").GetType("YourNamespace.YourType");

方案2:禁用Android程序集嵌入(不推荐)

如果必须通过文件路径读取DLL,可以修改项目配置禁用程序集嵌入,但会带来APK体积增大、启动速度变慢、安全性降低的问题。在项目的.csproj文件中添加:

<PropertyGroup Condition="'$(Configuration)' == 'Release' And '$(TargetFramework)' == 'net7.0-android'">
    <!-- 禁用程序集嵌入到APK -->
    <AndroidEmbedAssembliesIntoApk>false</AndroidEmbedAssembliesIntoApk>
</PropertyGroup>

内容的提问来源于stack exchange,提问作者TRex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 14:17:18