0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

KeyedServiceについて語る

Posted at

.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,こちらで設定ファイルに基づいてSMS通知の送信が完了します,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", "メール設定" } };    
  }
}

public class ISMSConfigRepository : IConfigRepository{    
  public Dictionary<string, dynamic> GetConfig()    {        
    // データベースから設定情報を取得する        
    return new Dictionary<string, dynamic>() { { "name", "SMS設定" } }; ;    
  }
}

最後に、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();

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段階であるためかもしれませんが、正式版での改善を期待しています。
(Translated by GPT)

元のリンク:https://mp.weixin.qq.com/s?__biz=MzA3NDM1MzIyMQ==&mid=2247487066&idx=1&sn=7e7222da26ede37c0c3b503a0736c773&chksm=9f005170a877d866bee7149c755b92a177953c178c05c2cf2c9bad401fc8443d0bd08cfe5d5d&token=2050451386&lang=zh_CN#rd

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?