写点什么

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

作者:newbe36524
  • 2023-02-22
    上海
  • 本文字数:1853 字

    阅读完需:约 6 分钟

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

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

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

有一个接口是这样的


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


并且由两个不同的实现


// Jsonpublic class MyJsonSerializer : ISerializer{    public byte[] Serialize<T>(T obj)    {        throw new NotImplementedException();    }
public T Deserialize<T>(ReadOnlySpan<byte> data) { throw new NotImplementedException(); }}
// MessagePackpublic 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 中是原生支持的。

参考


感谢您的阅读,如果您觉得本文有用,快点击下方点赞按钮👍,让更多的人看到本文。


欢迎关注作者的微信公众号“newbe 技术专栏”,获取更多技术内容。


发布于: 刚刚阅读数: 3
用户头像

newbe36524

关注

开源项目作者,独立博客维护者 2020-06-02 加入

newbe36524 是一名开发工程师。newbe 是 newbe36524 的个人技术博客。秉承 now everyone will be excellent 的 slogan 希望为开发者们分享自己的开发经验和心路历程。

评论

发布
暂无评论
aspnetcore 原生 DI 实现基于 key 的服务获取_C#_newbe36524_InfoQ写作社区