• .NET8中KeyedService的用法
  • 发布于 2个月前
  • 318 热度
    0 评论
  • 望北海
  • 0 粉丝 26 篇博客
  •   
在.NET8中,引入了KeyedService,用自定义关键字来使用服务,就是当注入多个接口子类的时候,可以通过命名关键字来区分,然后在使用时,使用关键字来调用。
下面看一个例子,通知服务接口INotifyService有两个子类,SMSService和EMailService。同时这些子类会调用不同的Respository。
public interface INotifyService
{
    bool Notify(string message);
}

public class SMSService : INotifyService
{
    private readonly Dictionary<string, dynamic> _configs;
    private readonly ILogger<EMailService> _logger;
    public SMSService([FromKeyedServices("smsRep")] IConfigRepository configRepository, ILogger<EMailService> logger)
    {
        _logger = logger;
        _configs = configRepository.GetConfig();
    }
    public bool Notify(string message)
    {
        _logger.LogInformation($"{_configs["name"]},SMSService,这里根据配置文件完成短信的通知发送,Message:{message}");
        return true;
    }
}
public class EMailService : INotifyService
{
    private readonly Dictionary<string, dynamic> _configs;
    private readonly ILogger<EMailService> _logger;
    public EMailService([FromKeyedServices("emailRep")] IConfigRepository configRepository, ILogger<EMailService> logger)
    {
        _logger = logger;
        _configs = configRepository.GetConfig();
    }
    public bool Notify(string message)
    {
        _logger.LogInformation($"{_configs["name"]},EMailService,这里根据配置文件完成邮件的通知发送,Message:{message}");
        return true;
    }
}
public interface IConfigRepository
{
    Dictionary<string, dynamic> GetConfig();
}
public class IEMailConfigRepository : IConfigRepository
{
    public Dictionary<string, dynamic> GetConfig()
    {
        //从数据库中获取配置信息
        return new Dictionary<string, dynamic>() { { "name", "email配置" } };
    }
}
public class ISMSConfigRepository : IConfigRepository
{
    public Dictionary<string, dynamic> GetConfig()
    {
        //从数据库中获取配置信息
        return new Dictionary<string, dynamic>() { { "name", "sms配置" } }; ;
    }
}
最后,再定义两个使用类SMS和EMail,在使上KeyedService时,需要用特性[FromKeyedServices("命名")],但这个特性不能直接使用在app.Map方法中,所以这里才有定义SMS和EMail两个类,再通过AddScoped的方式注放的写法。
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
using System.Collections;
using System.Collections.Generic;
var builder = WebApplication.CreateSlimBuilder(args);

builder.Services.AddScoped<SMS>();
builder.Services.AddScoped<EMail>();

builder.Services.AddKeyedScoped<IConfigRepository, ISMSConfigRepository>("smsRep");
builder.Services.AddKeyedScoped<IConfigRepository, IEMailConfigRepository>("emailRep");

builder.Services.AddKeyedScoped<INotifyService, EMailService>("emailSev");
builder.Services.AddKeyedScoped<INotifyService, SMSService>("smsSev");
var app = builder.Build();
// 堆代码 duidaima.com
app.MapGet("/sms", ([FromServices]SMS sms, string message) => new { Result = sms.Notify(message), Messgae = message, Type = sms.GetType().Name });
app.MapGet("/email", ([FromServices] EMail email, string message) => new { Result = email.Notify(message), Messgae = message, Type = email.GetType().Name });
//错误写法
//app.MapGet("/sms", ([FromKeyedServices("smsSev")] INotifyService notifyService, string message) => new { Result = notifyService.Notify(message), Messgae = message, Type = notifyService.GetType().Name });
//app.MapGet("/email", ([FromKeyedServices("smsSev")] INotifyService notifyService, string message) => new { Result = notifyService.Notify(message), Messgae = message, Type = notifyService.GetType().Name });

app.Run();

public class SMS([FromKeyedServices("smsSev")] INotifyService notifyService)
{
    public bool Notify(string message)
    {
        return notifyService.Notify(message);
    }
}
public class EMail([FromKeyedServices("emailSev")] INotifyService notifyService)
{
    public bool Notify(string message)
    {
        return notifyService.Notify(message);
    }
}
还有一种写法如下,可以做到简化,就是通过AddSingleton方式注入,然后用app.Services.GetRequiredKeyedService方式来获取通知接口,进行使用。
builder.Services.AddKeyedSingleton<IConfigRepository, IEMailConfigRepository>("emailRep");
builder.Services.AddKeyedSingleton<INotifyService, EMailService>("emailSev");
var app = builder.Build();
app.MapGet("/email", (string message) =>
{
    var email = app.Services.GetRequiredKeyedService<INotifyService>("emailSev");
    return new { Result = email.Notify(message), Messgae = message, Type = email.GetType().Name };
});
说说我使用的感受,感觉KeyedService使用有很多限制,不是很顺畅,也可能是Preview阶段,希望正式版本有所改善。
用户评论