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

Azure Function调用BuildManager.GetReferencedAssemblies()报错求助

解决Azure Functions中调用BuildManager.GetReferencedAssemblies()的错误

这个问题的核心在于BuildManager.GetReferencedAssemblies()是ASP.NET框架专属的方法,它依赖于ASP.NET的应用程序生命周期和加载机制,但Azure Functions的运行环境是独立的沙箱模型——不管是初始化阶段还是运行时,都不支持这个方法的调用,这就是你不管把它移到哪里都会报错的原因。

下面给你几个可行的解决方案:

1. 替换程序集扫描方式,用兼容Azure Functions的方法

放弃BuildManager,改用Azure Functions环境支持的程序集加载方式:

方案A:从当前应用域获取已加载的程序集

你可以通过AppDomain.CurrentDomain.GetAssemblies()获取当前已经加载到应用域的所有程序集,然后筛选出你需要的业务程序集:

var targetAssemblies = AppDomain.CurrentDomain.GetAssemblies()
    .Where(a => !a.IsDynamic && a.FullName.StartsWith("YourProjectNamespace."))
    .ToList();

这种方式简单直接,缺点是如果某些程序集是延迟加载的,可能不会出现在这个列表里。

方案B:从函数部署目录手动加载程序集

如果方案A没覆盖到你需要的程序集,可以直接从函数的部署目录加载所有相关DLL:

// 获取当前函数程序集的所在目录
var deploymentPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
// 遍历目录下的所有DLL文件
var assemblyFiles = Directory.GetFiles(deploymentPath, "*.dll", SearchOption.TopDirectoryOnly);
// 加载程序集(过滤掉系统程序集,比如Microsoft.*、System.*)
var targetAssemblies = assemblyFiles
    .Where(f => !Path.GetFileName(f).StartsWith("Microsoft.") && !Path.GetFileName(f).StartsWith("System."))
    .Select(f => Assembly.LoadFrom(f))
    .ToList();

这种方式能确保加载所有你部署的业务程序集,非常适合约定式注册的场景。

2. 调整Unity容器的初始化时机

IExtensionConfigProvider的Initialize方法属于Azure Functions的扩展初始化阶段,此时运行环境还未完全就绪,不适合做复杂的程序集扫描和容器初始化。建议把初始化逻辑移到函数的第一次调用阶段,用静态构造函数或者懒加载来实现:

示例:用静态构造函数初始化Unity容器

public class MyFunction
{
    // 静态容器实例,确保只初始化一次
    private static readonly IUnityContainer _unityContainer;

    static MyFunction()
    {
        _unityContainer = new UnityContainer();
        
        // 用上面的方案A或B获取目标程序集
        var targetAssemblies = AppDomain.CurrentDomain.GetAssemblies()
            .Where(a => !a.IsDynamic && a.FullName.StartsWith("YourNamespace."))
            .ToList();
            
        // 执行Unity的约定式注册
        _unityContainer.RegisterTypes(
            AllClasses.FromAssemblies(targetAssemblies),
            WithMappings.FromMatchingInterface,
            WithName.Default,
            WithLifetime.Transient);
    }

    [FunctionName("MySampleFunction")]
    public async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req,
        ILogger log)
    {
        // 从容器解析服务
        var myService = _unityContainer.Resolve<IMyBusinessService>();
        // 执行业务逻辑...
        return new OkObjectResult("Success");
    }
}

静态构造函数会在类第一次被访问时执行,此时Azure Functions的运行环境已经完全就绪,程序集也都加载完成,不会再出现初始化阶段的错误。

3. 可选:改用Azure Functions原生依赖注入

如果你不需要Unity的特定功能,其实Azure Functions已经支持原生的依赖注入(基于Microsoft.Extensions.DependencyInjection),这种方式更贴合Functions的运行环境,也能避免Unity和环境兼容的问题:

你可以创建一个Startup类来配置DI:

using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;

[assembly: FunctionsStartup(typeof(YourNamespace.Startup))]
namespace YourNamespace
{
    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            // 获取目标程序集
            var targetAssemblies = AppDomain.CurrentDomain.GetAssemblies()
                .Where(a => !a.IsDynamic && a.FullName.StartsWith("YourNamespace."))
                .ToList();
                
            // 注册所有符合约定的服务(示例:注册所有实现了接口的类)
            foreach (var assembly in targetAssemblies)
            {
                var types = assembly.GetTypes()
                    .Where(t => t.IsClass && !t.IsAbstract && t.GetInterfaces().Any());
                foreach (var type in types)
                {
                    var interfaceType = type.GetInterfaces().First();
                    builder.Services.AddTransient(interfaceType, type);
                }
            }
        }
    }
}

然后在函数里直接通过构造函数注入服务即可,不需要手动管理容器。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:09:04