在Azure函数启动中调用MethodInfo.Invoke失败

问题描述

我有一个.Net Core 3.1应用程序,该应用程序被实现为Azure功能(v3),但在启动时失败。在函数应用程序项目中,我实现了一个Startup类,该类将各种服务添加到IServiceCollection集合中以进行依赖项注入。我有一个程序集,需要使用反射手动加载,然后调用一个方法,该方法会将该程序集中定义的所有服务添加到IServiceCollection集合中。如您在下面看到的,失败的是行method.Invoke(null,new Object[] { services });。加载程序集,获取类型信息或方法信息似乎没有问题,因为此代码中没有抛出任何异常。您可以看到我正在调用静态类的静态方法,因此调用了null方法的Invoke参数。我尝试使用非静态类并使用Activator.CreateInstance方法将对象实例传递给Invoke方法,但遇到相同的错误。该代码在本地运行时可以执行而没有错误,并且仅在发布到Azure Function资源后才似乎有问题。

这是我的Startup.cs文件的内容:

using System;
using System.IO;
using System.Reflection;
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;

[assembly: FunctionsStartup(typeof(Some.Name.Space.FunctionApp.Startup))]
namespace Some.Name.Space.FunctionApp
{
    public sealed class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            IServiceCollection services = builder.Services;

            var assemblyNamespace = "Some.Name.Space";
            String? baseDirectory = Path.GetDirectoryName(GetType().Assembly.Location);
            if (!String.IsNullOrEmpty(baseDirectory))
            {
                Assembly assembly = Assembly.Load(File.ReadAllBytes(Path.Combine(baseDirectory,$"{assemblyNamespace}.dll")));
                var typeName = $"{assemblyNamespace}.SomeClassName";
                Type? type = assembly.GetType(typeName);
                if (type != null)
                {
                    var methodName = "SomeMethodName";
                    MethodInfo? method = type.GetMethod(methodName);
                    if (method != null)
                    {
                        method.Invoke(null,new Object[] { services });  // THIS IS LINE THAT FAILS.
                    }
                    else
                    {
                        throw new MissingMethodException($"Unable to find the {methodName} method in the {typeName} type.");
                    }
                }
                else
                {
                    throw new TypeLoadException($"Unable to load {typeName} from {assembly.GetName()}.");
                }
            }
            else
            {
                throw new DirectoryNotFoundException("Unable to get the Location directory for the function application.");
            }
        }
    }
}

我知道下面的错误消息不能正确描述问题,因为如果我简单地注释掉失败的一行,并且还有很多其他依赖于“ Microsoft”的代码,则整个应用程序都可以正常运行。 Extensions.DependencyInjection.Abstractions的程序集。这是我在Azure中看到的错误的屏幕截图:

enter image description here

解决方法

我不能坦白地说我的解决方案为什么起作用,但是我怀疑它与Assembly.Load(AssemblyName assemblyRef)方法如何使用System.Runtime.Loader.AssemblyLoadContext类有关。我怀疑我的原始实现没有加载正确的程序集,即使它能够加载我期望的名称的程序集。下面的解决方案具有默认的VersionCulturePublicKeyToken值供显示,因此您在实现中需要为这些属性使用正确的值。

以下是新的Startup.cs文件的内容:

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

[assembly: FunctionsStartup(typeof(Some.Name.Space.FunctionApp.Startup))]
namespace Some.Name.Space.FunctionApp
{
    public sealed class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            IServiceCollection services = builder.Services;
            var assemblyNamespace = "Some.Name.Space";
            AssemblyName assemblyName = new AssemblyName($"{assemblyNamespace},Version=1.0.0.0,Culture=neutral,PublicKeyToken=null");
            Assembly assembly = Assembly.Load(assemblyName);
            var typeName = $"{assemblyNamespace}.SomeType";
            Type? type = assembly.GetType(typeName);
            if (type != null)
            {
                var methodName = "SomeMethod";
                MethodInfo? method = type.GetMethod(methodName);
                if (method != null)
                {
                    method.Invoke(null,new Object[] { services });
                }
                else
                {
                    throw new MissingMethodException($"Unable to find the {methodName} method in the {typeName} type.");
                }
            }
            else
            {
                throw new TypeLoadException($"Unable to load {typeName} from {assembly.GetName()}.");
            }
        }
    }
}

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...