你可能想通過一個字符串或者其他的類型來獲取一個具體的服務實現,那麼在 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 中是原生支持的。
參考
感謝閱讀,如果覺得本文有用,不妨點擊推薦👍或者在評論區留下 Mark,讓更多的人可以看到。
歡迎關注作者的微信公衆號“newbe技術專欄”,獲取更多技術內容。
- 本文作者: newbe36524
- 本文鏈接: https://www.newbe.pro/Others/0x023-aspnetcore-natively-implements-key-based-service-resolving/
- 版權聲明: 本博客所有文章除特別聲明外,均採用 BY-NC-SA 許可協議。轉載請註明出處!
-
https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection-guidelines?WT.mc_id=DX-MVP-5003606↩