你可能想通过一个字符串或者其余的类型来获取一个具体的服务实现,那么在 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 中是原生反对的。

参考

  • Dependency injection guidelines1

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

欢送关注作者的微信公众号“newbe技术专栏”,获取更多技术内容。
  • 本文作者: newbe36524
  • 本文链接: https://www.newbe.pro/Others/0x023-aspnetcore-natively-implements-key-based-service-resolving/
  • 版权申明: 本博客所有文章除特地申明外,均采纳 BY-NC-SA 许可协定。转载请注明出处!

  1. https://learn.microsoft.com/e... ↩