鉴于以下事实服务描述符类 https://github.com/aspnet/DependencyInjection/blob/d5e5aa703297b164b21ba4ad3fdff81c854ce009/src/DI.Abstractions/ServiceDescriptor.cs没有Name
属性或任何设置字符串标识符的方法,并且用于解析服务的类被标记为内部,我想说答案是no.
然而,构建自己的扩展来伪造它并不是很困难。
命名服务描述符
class NamedServiceDescriptor
{
public NamedServiceDescriptor(string name, Type serviceType)
{
this.Name = name;
this.ServiceType = serviceType;
}
public string Name { get; private set; }
public Type ServiceType { get; private set; }
public override bool Equals(object obj)
{
if (!(obj is NamedServiceDescriptor))
return false;
var other = (NamedServiceDescriptor)obj;
return Name.Equals(other.Name, StringComparison.OrdinalIgnoreCase) &&
ServiceType.Equals(other.ServiceType);
}
public override int GetHashCode()
{
return Name.GetHashCode() ^
ServiceType.GetHashCode();
}
}
扩展方法
public static class ServiceCollectionExtensions
{
internal static readonly IDictionary<NamedServiceDescriptor, Type> nameToTypeMap
= new ConcurrentDictionary<NamedServiceDescriptor, Type>();
public static IServiceCollection AddSingleton<TService, TImplementation>(
this IServiceCollection serviceCollection,
string name)
where TService : class where TImplementation : class, TService
{
nameToTypeMap[new NamedServiceDescriptor(name, typeof(TService))]
= typeof(TImplementation);
return serviceCollection.AddSingleton<TImplementation>();
}
}
public static class ServiceProviderExtensions
{
public static T GetService<T>(this IServiceProvider provider, string name)
{
if (provider == null)
throw new ArgumentNullException(nameof(provider));
if (string.IsNullOrEmpty(name))
throw new ArgumentNullException(nameof(name));
ServiceCollectionExtensions.nameToTypeMap.TryGetValue(
new NamedServiceDescriptor(name, typeof(T)), out Type implementationType);
return (T)provider.GetService(implementationType);
}
}
Usage
public interface IMyReusableViewModel { }
public class MyReusableViewModel1 : IMyReusableViewModel { }
public class MyReusableViewModel2 : IMyReusableViewModel { }
IServiceCollection collection = new ServiceCollection();
collection.AddSingleton<IMyReusableViewModel, MyReusableViewModel1>("View1");
collection.AddSingleton<IMyReusableViewModel, MyReusableViewModel2>("View2");
public class MyService
{
private readonly IServiceProvider provider;
public MyService(IServiceProvider provider)
{
this.provider = provider;
}
public void DoSomething()
{
var view1 = provider.GetService<IMyReusableViewModel>("View1");
var view2 = provider.GetService<IMyReusableViewModel>("View2");
// ...
}
}
NOTE:也就是说,我不会推荐这种方法。如果您需要此类功能,则表明应用程序设计不充分。设计模式如抽象工厂 https://sourcemaking.com/design_patterns/abstract_factory or Strategy https://stackoverflow.com/a/32415954可能需要填补空白,而不需要诉诸命名类型注册或滥用容器作为服务定位器 http://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/.
或者,您可以使用支持此功能的第 3 方 DI 容器。