使用MS DI提供多种服务

时间:2018-03-12 08:59:50

标签: .net-core

我想提供一个服务来做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
{
    ....
}

我在People()中尝试做GetPhone()但是没办法

如何做这项服务?

我的服务代码

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

主程序:

select * from annotations where imagename='00003.jpg' x <= 510 order by x desc limit 1;

1 个答案:

答案 0 :(得分:1)

您需要能够使用同一接口(iphone4S)的多个实现(iphone5SIPhone)。 Microsoft.Extensions.DependencyInjection没有对此方案的内置支持。但是,这种限制有许多变通方法。我认为最好的之一(描述here)是根据输入参数注册工厂和创建所需实例。

要使用它,您应该注入IPhonePeople构造函数,而不是工厂Func<Type, IPhone>。然后在Use方法中,您知道实现的类型(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()方法中,您应该只注册工厂和所有可能的实现:

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"));

<强>更新

如果你有IPhone接口的很长的实现列表,你可以使用基于反射的方法注册它们:

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"));

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