1

我正在尝试将接口和设置传递给一个类,同时在 .Net Core 项目的 startup.cs 中创建该类的实例。我正在使用下面的代码来做到这一点。我在 Student 类的构造函数中编写了一些代码,但是在启动应用程序时,构造函数中的代码/逻辑不起作用。没有错误,但调试指针没有命中 Student 类的构造函数。

services.AddSingleton(c => new Student(settings, resourceSetting, c.GetService<IPersonService>()));

如果我使用下面的代码,那么 Student 构造函数中的代码工作正常。

 Student studentHandler = new Student(settings, resourceSetting,);
 services.AddSingleton<Student>(studentHandler);

但是我需要在构造函数中传递服务接口才能在启动项目时做一些工作。谁能帮我解决我在这里缺少的东西?

4

2 回答 2

5

调试指针未命中 Student 类的构造函数

这是因为您在第一个片段中将类型注册为实现工厂,使用AddSingleton<TService> (this IServiceCollection services, Func<IServiceProvider,TService> implementationFactory)此方法,在解决依赖关系之前Student不会调用实现工厂委托(以及随后的构造函数)。

在第二个片段中,您在服务注册时直接实例化类型,并将该实例添加到服务集合中AddSingleton<TService> (this IServiceCollection services, TService implementationInstance)


这是一个示例,其中的日志解释了每种方法中的每个步骤:

class Program
{
    static void Main(string[] args)

    {
        RegisterImplementationFactory();
        RegisterImplementation();
    }

    static void RegisterImplementationFactory()
    {
        Console.WriteLine("RegisterImplementationFactory ------------");

        var services = new ServiceCollection();

        Console.WriteLine("Registering Student...");
        services.AddSingleton(c => new Student());
        Console.WriteLine("Student registered.");

        Console.WriteLine("Building ServiceProvider...");
        var serviceProvider = services.BuildServiceProvider();
        Console.WriteLine("ServiceProvider built.");

        Console.WriteLine("Resolving Student...");
        Student student = serviceProvider.GetService<Student>();
        Console.WriteLine("Student resolved.");

        Console.WriteLine("RegisterImplementationFactory ------------");
        Console.WriteLine();
    }

    static void RegisterImplementation()
    {
        Console.WriteLine("RegisterImplementation ------------");

        var services = new ServiceCollection();

        Console.WriteLine("Registering Student...");
        Student studentToRegister = new Student();
        services.AddSingleton(studentToRegister);
        Console.WriteLine("Student registered.");

        Console.WriteLine("Building ServiceProvider...");
        var serviceProvider = services.BuildServiceProvider();
        Console.WriteLine("ServiceProvider built.");

        Console.WriteLine("Resolving Student...");
        Student student = serviceProvider.GetService<Student>();
        Console.WriteLine("Student resolved.");

        Console.WriteLine("RegisterImplementation ------------");
        Console.WriteLine();
    }
}

class Student
{
    public Student()
    {
        Console.WriteLine("!!! Instantiating Student...");
    }
}

这个的输出是:

RegisterImplementationFactory ------------
Registering Student...
Student registered.
Building ServiceProvider...
ServiceProvider built.
Resolving Student...
!!! Instantiating Student...
Student resolved.
RegisterImplementationFactory ------------

RegisterImplementation ------------
Registering Student...
!!! Instantiating Student...
Student registered.
Building ServiceProvider...
ServiceProvider built.
Resolving Student...
Student resolved.
RegisterImplementation ------------

有了这个,您可以清楚地看到,在使用工厂委托进行注册时,在Student解析类型之前不会调用构造函数(GetService<Student>()在本例中为 with)。

于 2020-12-16T19:29:16.453 回答
0

您似乎正在使用依赖注入,因此我建议您根据您的构造函数进一步利用 DI 引擎。

首先,您将要注册settingsresourceSetting对象

services.AddSingleton<Student>(settings);
services.AddSingleton<Student>(resourceSetting);

然后也注册你的Student课程

services.AddSingleton<Student>();

现在,一旦您将您的内容构建ServiceCollectionServiceProvidervia.BuildServiceProvider();中(如果您正在制作控制台应用程序),您可以调用:

var myStudent = myServiceProvider.GetRequiredService<Student>();

如果您在 asp.net 之类的东西中执行此操作,那么您只需将您的Student类注入控制器或其他此类服务以供使用

class MyController : ControllerBase
{

    private Student Student { get; }

    public MyController(Student student)
    {
       Student = student ?? throw new ArgumentNullException(nameof(student));
    }
 
    ...
}
于 2020-12-16T19:31:08.957 回答