.NE5 自带的 IoC 不支持命名, 无法实现按名称获取实例. 原来的项目是用 Unity
, 在.NET5 里也可以使用:
Program.cs
Host.CreateDefaultBuilder(args)
//内置 IoC 不支持命名, 所以这里依然使用 Unity Container 做为 IoC 容器
//https://github.com/unitycontainer/microsoft-dependency-injection
.UseUnityServiceProvider()
Startup.cs
/// <summary>
/// 使用 Unity 替代自带的 IoC, 因为自带的 IoC 不支持命名
/// </summary>
/// <param name="container"></param>
public void ConfigureContainer(IUnityContainer container)
{
//加这个会报错...
//container.AddExtension(new Diagnostic());
...
...
usl = new UnityServiceLocator(container);
ServiceLocator.SetLocatorProvider(() => usl);
}
虽然 Unity 也是微软的项目, 但是终究不是自带的。。。
而且 使用 Diagnostic
会报错, 具体原因没有细找。
新项目我换了种方式:
维护一份名称和类型的映射关系 ,IoC 正常注册。
获取实例的时候, 先用名称获取类型, 在用类型获取实例。
不是很完美,但是能解决问题:
public static class ServiceExtension
{
/// <summary>
///
/// </summary>
private static readonly ConcurrentDictionary<string, Type> dic = new();
/// <summary>
///
/// </summary>
/// <param name="service"></param>
/// <param name="name"></param>
public static void WithName<T>(this IServiceCollection service, string name, RegistMode mode) where T : class
{
WithName(service, typeof(T), name, mode);
}
/// <summary>
///
/// </summary>
/// <param name="service"></param>
/// <param name="type"></param>
/// <param name="name"></param>
/// <param name="mode"></param>
public static void WithName(this IServiceCollection service, Type type, string name, RegistMode mode)
{
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentException($"{nameof(name)} 不能为空");
if (!dic.TryAdd(name.ToUpper(), type))
{
throw new InvalidOperationException($"{name} 已经存在,不能重复注册");
}
else
{
switch (mode)
{
case RegistMode.Singleton:
service.AddSingleton(type);
break;
case RegistMode.Transient:
service.AddTransient(type);
break;
case RegistMode.Scoped:
service.AddScoped(type);
break;
default:
service.AddScoped(type);
break;
}
}
}
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="sp"></param>
/// <param name="name"></param>
/// <returns></returns>
public static T GetService<T>(this IServiceProvider sp, string name)
{
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentException($"{nameof(name)} 不能为空");
if (dic.TryGetValue(name.ToUpper(), out Type t))
{
return (T)sp.GetService(t);
}
else
{
//throw new InvalidOperationException($"{name} 未注册");
return default;
}
}
}