【发布时间】:2020-08-28 18:23:38
【问题描述】:
我有一个 .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 中看到的错误的屏幕截图:
【问题讨论】:
-
您在该例程中动态加载的库需要
Microsoft.Extensions.DependencyInjection.Abstractions命名空间。因此,请确保打包此 nuget 包:nuget.org/packages/… 如果您的项目已导入该包,请将您正在加载的库与您的 Azure 函数 dll 放在同一目录中。 -
我动态加载的库确实使用了
Microsoft.Extensions.DependencyInjection命名空间。该库通过使用的单独包间接引用了“Microsoft.Extensions.DependencyInjection.Abstractions.dll”(该单独包引用了 *.Abstractions.dll 包)。 -
另外,如果我删除反射功能,并设置对包的项目/程序集引用并直接调用该方法(它作为
IServiceCollection接口的扩展方法实现),那么一切正常.在我的情况下,我不需要有对我试图动态加载的这个库的项目/程序集引用。
标签: c# .net-core azure-functions system.reflection methodinfo