任何方式来命名相同类型的倍数?

注意:使用.NET Core 2.0 [Microsoft.Extensions.DependencyInjection]。

这就是我想做的事情:

IServiceCollection collection = new ServiceCollection(); collection.AddSingleton(nameof(View1)); collection.AddSingleton(nameof(View2)); 

但我无法找到一种方法来命名添加到集合中的服务。 如果在未指定名称的情况下重复使用的类型,则该集合似乎只是用新的服务覆盖现有服务。 理想情况下,我可以重用一个类型,但通过提供名称来区分它。

请忽略这个人为的例子。

问:这可能吗?

鉴于ServiceDescriptor类没有Name属性或任何设置字符串标识符的方法,并且解析服务的类被标记为内部,我会说答案是否定的


但是,构建自己的扩展来伪造它并不是很困难。

NamedServiceDescriptor

 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 nameToTypeMap = new ConcurrentDictionary(); public static IServiceCollection AddSingleton( this IServiceCollection serviceCollection, string name) where TService : class where TImplementation : class, TService { nameToTypeMap[new NamedServiceDescriptor(name, typeof(TService))] = typeof(TImplementation); return serviceCollection.AddSingleton(); } } public static class ServiceProviderExtensions { public static T GetService(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); } } 

用法

 public interface IMyReusableViewModel { } public class MyReusableViewModel1 : IMyReusableViewModel { } public class MyReusableViewModel2 : IMyReusableViewModel { } IServiceCollection collection = new ServiceCollection(); collection.AddSingleton("View1"); collection.AddSingleton("View2"); public class MyService { private readonly IServiceProvider provider; public MyService(IServiceProvider provider) { this.provider = provider; } public void DoSomething() { var view1 = provider.GetService("View1"); var view2 = provider.GetService("View2"); // ... } } 

注意:那就是说,我不推荐这种方法。 如果您需要此类function,则表明应用程序设计不足。 诸如抽象工厂或策略之类的设计模式可能是填充空白而不诉诸命名类型注册或滥用容器作为服务定位器所需要的 。

或者,您可以使用支持此function的第三方DI容器。