天天看点

aspnetcore 原生 DI 实现基于 key 的服务获取

作者:opendotnet

你可能想通过一个字符串或者其他的类型来获取一个具体的服务实现,那么在 aspnetcore 原生的 MSDI 中,如何实现呢?本文将介绍如何通过自定义工厂来实现。

我们现在恰好有基于 Json 和 MessagePack 的两种序列化器

有一个接口是这样的

public interface ISerializer
{
byte[] Serialize<T>(T obj);
T Deserialize<T>(ReadOnlySpan<byte> data);
}
           

并且由两个不同的实现

// Json
public class MyJsonSerializer : ISerializer
{
public byte[] Serialize<T>(T obj)
 {
throw new NotImplementedException();
 }

public T Deserialize<T>(ReadOnlySpan<byte> data)
 {
throw new NotImplementedException();
 }
}

// MessagePack
public class MyMessagePackSerializer : ISerializer
{
public byte[] Serialize<T>(T obj)
 {
throw new NotImplementedException();
 }

public T Deserialize<T>(ReadOnlySpan<byte> data)
 {
throw new NotImplementedException();
 }
}
           

我有一个服务,需要使用这两种序列化器中的一种。

public class MyService
{
public object DoSomething(string dataType, ReadOnlySpan<byte> data)
 {
 // 根据 dataType 来决定使用哪种序列化器
 }
}
           

使用委托来定义获取服务的方法

我们可以通过委托来定义获取服务的方法,如下

public delegate ISerializer SerializerFactory(string dataType);
           

然后在

ConfigureServices

方法中注册

services.AddSingleton<MyJsonSerializer>();
services.AddSingleton<MyMessagePackSerializer>();
services.AddSingleton<SerializerFactory>(sp =>
{
return dataType =>
 {
switch (dataType)
 {
case "json":
return sp.GetRequiredService<MyJsonSerializer>();
case "msgpack":
return sp.GetRequiredService<MyMessagePackSerializer>();
 default:
throw new NotSupportedException();
 }
 };
});
           

这样我们就可以在

MyService

中通过委托来获取服务了

public class MyService
{
private readonly SerializerFactory _serializerFactory;

public MyService(SerializerFactory serializerFactory)
 {
 _serializerFactory = serializerFactory;
 }

public object DoSomething(string dataType, ReadOnlySpan<byte> data)
 {
var serializer = _serializerFactory(dataType);
return serializer.Deserialize<object>(data);
 }
}
           

基于配置来改变工厂

因为本质是通过委托来获取服务,所以我们可以通过配置来改变委托的行为,如下

public static class SerializerFactoryExtensions
{
public static SerializerFactory CreateSerializerFactory(this IServiceProvider sp)
 {
 // get mapping from configuration
var mapping = sp.GetRequiredService<IConfiguration>()
 .GetSection("SerializerMapping")
 .Get<Dictionary<string, string>>();
return dataType =>
 {
var serializerType = mapping[dataType];
return (ISerializer)sp.GetRequiredService(Type.GetType(serializerType));
 };
 }
}
           

然后在

appsettings.json

中配置

{
 "SerializerMapping": {
 "json": "WebApplication1.MyJsonSerializer",
 "msgpack": "WebApplication1.MyMessagePackSerializer"
 }
}
           

然后在

ConfigureServices

方法中注册

services.AddSingleton<MyJsonSerializer>();
services.AddSingleton<MyMessagePackSerializer>();
services.AddSingleton(SerializerFactoryExtensions.CreateSerializerFactory);
           

总结

本篇文章介绍了如何通过自定义工厂来实现基于 key 的服务获取,这种方式在 aspnetcore 原生的 DI 中是原生支持的。

参考

  • Dependency injection guidelines1
欢迎加入Q群 610394020,进入腾讯最新功能类Discord功能: QQ 频道。 在 QQ 频道中,你可以:
  • 在技术专区发帖求教
  • 在摸鱼频道畅快遨游
  • 在会议频道一同讨论 让我们一同打造和谐社区。
  • 本文作者: newbe36524
  • 本文链接: https://www.newbe.pro/Others/0x023-aspnetcore-natively-implements-key-based-service-resolving/
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  1. https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection-guidelines?WT.mc_id=DX-MVP-5003606↩

继续阅读