.net core 使用MS DI提供多种服务

.net core 使用MS DI提供多种服务,.net-core,.net Core,我想提供一个服务来做GetPhone() 像这样 provider.GetService<People>().GetPhone(iphone4S).Use<IPhone>(phone => phone.Call("123456")); provider.GetService().GetPhone(iphone4S).Use(phone=>phone.Call(“123456”); 我试着在People()中做GetPhone()但是不行 如何做这项服务 我的服务

我想提供一个服务来做GetPhone()

像这样

provider.GetService<People>().GetPhone(iphone4S).Use<IPhone>(phone => phone.Call("123456"));
provider.GetService().GetPhone(iphone4S).Use(phone=>phone.Call(“123456”);
我试着在People()中做GetPhone()但是不行

如何做这项服务

我的服务代码

public interface IPhone
{
    string Call(string Num);
}
public class People 
{
    private IPhone _phone;
    public People(IPhone phone) => this._phone = phone;

    public void Use<TPhone>(Action<IPhone> config)
        where TPhone : class, IPhone
    {
        config(this._phone);
    }
    public IPhone GetPhone()
    {
        return this._phone;
    }
}
public class iphone4S : IPhone
{
    ....
}

public class iphone5S : IPhone
{
    ....
}
公共界面IPhone { 字符串调用(string Num); } 公营阶层人士 { 私人IPhone(u)电话;; 公众人士(IPhone手机)=>这个; 公共无效使用(操作配置) 其中TPhone:class,IPhone { 配置(本手机); } 公共IPhone GetPhone() { 把这个还给我; } } 公共级iphone4S:IPhone { .... } 公共级iphone5S:IPhone { .... } 主程序:

ServiceProvider provider = new ServiceCollection()
         .AddSingleton<People>()
         .BuildServiceProvider();
Provider.GetService<People>().GetPhone(iphone4S).Use<IPhone>(phone => phone.Call("123456"));
ServiceProvider=newServiceCollection()
.AddSingleton()
.BuildServiceProvider();
Provider.GetService().GetPhone(iphone4S).Use(phone=>phone.Call(“123456”);

您需要能够使用同一界面(
iphone4S
iphone5S
)的多个实现(
IPhone
)。Microsoft.Extensions.DependencyInjection没有对此方案的内置支持。然而,有许多解决这一限制的办法。在我看来,最好的方法之一是注册工厂,并根据输入参数创建所需的实例

要使用它,您不应该将
IPhone
注入
People
构造函数,而应该将factory
Func
注入。然后在
中使用
方法,在该方法中,您知道实现的类型(
TPhone
),您可以使用以下方法创建一个实例:

public class People
{
    private readonly Func<Type, IPhone> phoneFactory;
    private IPhone _phone;

    public People(Func<Type, IPhone> phoneFactory) => this.phoneFactory = phoneFactory;

    public void Use<TPhone>(Action<IPhone> config) where TPhone : class, IPhone
    {
        _phone = phoneFactory(typeof(TPhone));
        config(this._phone);
    }

    public IPhone GetPhone()
    {
        return this._phone;
    }
}

如果在
Main()
method所在的同一程序集中定义了实现类,那么这将起作用。如果实现是在不同的程序集中定义的,您可以通过枚举所有加载的程序集来调整此方法,如本文所述。

您想做什么?如果希望基于当前模型对服务使用不同的实现,只需在运行时检测模型并仅注册适当的服务即可。如果你想根据用户提供的数据找到一个对象,你要求的是数据检索,而不是依赖注入。电话型号在DI配置和呼叫之间不会改变。OP不必指定要使用的服务,只需注册相应的服务。然后,为什么OP在
use
call中将
TPhone
指定为参数?这是一个非常有趣的问题。我怀疑这是XY问题的一个例子。在运行时选择特定的实现是一个有效的方案。MarkSeemann在他的名著《.NET中的依赖注入》中用了整整一节来讨论这个问题(6.1.将运行时值映射到抽象)。我没说不是。注册10个变体是没有意义的,尽管只有一个可以使用,这是在启动时知道的
ServiceProvider provider = new ServiceCollection()
    .AddSingleton<People>()
    .AddTransient<iphone4S>()
    .AddTransient<iphone5S>()
    .AddTransient(factory => (Func<Type, IPhone>)(type => (IPhone)factory.GetService(type)))
    .BuildServiceProvider();

provider.GetService<People>().Use<iphone5S>(phone => phone.Call("123456"));
var services = new ServiceCollection();
services.AddSingleton<People>()
    .AddTransient(factory => (Func<Type, IPhone>)(type => (IPhone)factory.GetService(type)));

foreach (var iphoneType in Assembly.GetExecutingAssembly().GetTypes()
    .Where(t => !t.IsAbstract)
    .Where(t => typeof(IPhone).IsAssignableFrom(t)))
{
    services.AddTransient(iphoneType);
}

var provider = services.BuildServiceProvider();
provider.GetService<People>().Use<iphone5S>(phone => phone.Call("123456"));