2

我试图弄清楚如果我将这些属性应用于某些服务然后将其注入 DI 将使用哪个CallerMemberName或值。CallerFilePath例如:

public class MyService: IMyService
{
    public MyService([CallerMemberName] string name = null)
    {
        var name = name; // name is always null here
    }
}

...

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddScoped<IMyService, MyService>();
    }
}

所以,我想,它是name变量的预期值还是我做错了什么?在这种情况下我该如何CallerMemberName处理?有可能吗?

4

1 回答 1

6

我试图弄清楚如果我将这些属性应用于某些服务然后将其注入 DI 将使用哪个CallerMemberName或值。CallerFilePath

你不能。您的方法不起作用,因为 ASP.NET Core ( Microsoft.Extensions.DependencyInjection) 使用的默认 DI 系统使用动态注册,这意味着 AOT (C#-to-IL) 和 JIT (IL-to-x64) 编译器都不知道一个 DI 服务(请注意,虽然注册在概念上是静态的,并且只能在启动时执行 - 这只是一种错觉:您可以在运行时轻松破解默认 DI 容器)。

作为补充:您的方法唯一可行的情况是,如果您有某种代码生成系统来在构建时创建您的对象工厂和服务工厂,而不使用任何运行时反射或 IL 生成。在实践中,您看到该方法的唯一地方是在单元测试代码中使用它,在这些代码中测试需要严格控制每个依赖项——但它们通常是手工编写的,而且非常乏味和脆弱。通过 Roslyn 代码生成,我希望看到静态服务工厂开始被更多地使用,因为它为您提供了编译时保证每个依赖项都可用 - 这样您就不会在运行时遇到任何关于缺少依赖项的令人讨厌的意外。

[CallerMemberName]and[CallerFilePath]属性由 AOT 编译器而不是 JIT 编译器填充,即使它是由 JIT 编译器填充的,它也无济于事,因为DI服务的使用者不是服务构造函数的调用者

难道我做错了什么?

你是。由于我上面描述的原因。

在这种情况下我该如何CallerMemberName处理?

你不能。CallerMemberNameAttribute不用于此目的。它旨在用于快速简便的日志记录、分析和跟踪。

有可能吗?

是的 - 通过正确扩展Microsoft.Extensions.DependencyInjection。请阅读 MEDI 文档以获取更多详细信息。

于 2021-02-23T11:32:45.453 回答