构建IServiceProvider后如何添加服务?

问题描述 投票:0回答:2

这些是一些定义:

public interface IClassA
{
    
}
public class ClassA : IClassA
{
    public ClassA()
    {
        Init();
    }

    private void Init()
    {
        Console.WriteLine("Hello!!!");
    }
}
public class ClassB
{
    private IClassA _classA;
    public ClassB(IClassA classA)
    {
        this._classA = classA;
    }
}

如果我构建服务提供者,则在我向 ioc 容器添加更多服务并获取它们后,单例实例将被创建两次或更多次。

IServiceCollection serviceCollection = new ServiceCollection();
serviceCollection.TryAddSingleton<IClassA,ClassA>();
ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
serviceProvider.GetRequiredService<IClassA>();


serviceCollection.TryAddSingleton<ClassB>();
serviceProvider = serviceCollection.BuildServiceProvider();
serviceProvider.GetRequiredService<ClassB>();

输出为:

Hello!!!
Hello!!!

表示ClassA实例被创建了两次。 我想在第一阶段向 ioc 容器添加一些服务后使用 ServiceProvider。我想在第二阶段向容器中添加一些服务并获取一些服务。 但是,如何确保在第二阶段获得服务后仍会创建单例服务。

c# ioc-container
2个回答
2
投票

由于每个

IServiceProvider
分别跟踪自己的服务,因此使用注册类型的方法将无法正常工作,因为每个提供者最终都会实例化单例,从而导致如您所见的 2 个不同的实例。

如果你真的想要有 2 个提供者(一般来说这是一个坏主意),你可以通过将实例传递给容器来解决这个问题:

var classA = new ClassA();
IServiceCollection serviceCollection = new ServiceCollection();
serviceCollection.AddSingleton<IClassA>(classA);
ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
serviceProvider.GetRequiredService<IClassA>();


serviceCollection.TryAddSingleton<ClassB>();
serviceProvider = serviceCollection.BuildServiceProvider();
serviceProvider.GetRequiredService<ClassB>();

当解析来自任一提供者的任何内容时,它不会尝试实例化该类型,因为您显式提供了实例。

然而,这是一种相当老套的方法,我不会推荐它,除非它确实是你的最后选择。


0
投票
    public static void AddScopedPostBuild<TService>(this ServiceProvider serviceProvider, Func<IServiceProvider, TService> implementationFactory) where TService : class
    {
        var serviceType = typeof(TService);
        var callSiteFactory = serviceProvider.GetPrivatePropertyValue<object>("CallSiteFactory");
        var serviceIdentifier = fromServiceTypeMethod.Invoke(null, [ (object)typeof(TService) ]);
        var objImplementation = implementationFactory(serviceProvider);
        var callSite = constantCallSiteConstructor.Invoke([ typeof(TService), objImplementation ]);

        callSiteFactory.CallMethod("Add", serviceIdentifier, callSite);
    }

使用https://www.nuget.org/packages/Utils.Core

© www.soinside.com 2019 - 2024. All rights reserved.