我有以下问题:
我有2
服务:
Sa
Sb
。
为了使用户能够使用sb
他需要在Sa
中执行一项操作,这将授予他token
。
然后,他将使用此token
来执行将在Sb
上执行的所有操作。
我不希望Sb
的所有方法都需要token
作为参数。我想从一开始就将Sb
插入servicecollection
中,并能够存储token
作为内部属性(在用户使用Sa
之后),
我该怎么做?如何根据另一个服务中的操作更改注入的服务。
授予令牌的服务
public class Sa{
//grants token
public string GrantToken(string username);
}
对事件具有可设置属性的服务
public class Sb{
private internalService internalService;
public ClassName(InternalService internalService)
{
this.internalService=internalService;
}
public string Token{get;set;}
///all these actions would need the user to provide the token as parameter
/// i want to somehow set the `Token` property of Sb after the Sa grants the token
public void Action1(/*string token */){
this.internalService.DoAction1(Token);
}
public void Action2(/*string token */){
this.internalService.DoAction2(Token);
}
public void ActionN(){
this.internalService.DoActionN(Token);
}
}
//internal service that needs the token
public class InternalService
{
public void DoAction1(string token);
public void DoAction2(string token);
//.....//
public void DoActionN(string token);
}
`
启动
public void ConfigureServices(IServiceCollection services) {
Sa sa=new Sa();
Sb sb=new Sb(); //i want this injected from the get-go but to have the `Token` property set-able
InternalService ins=new InternalService();
services.AddSingleton(ins);
services.AddTransient(sa);
services.AddTransient(sb);
}
场景
///我们所在的类中有一个Sa和一个Sb
var token=sa.GrantToken();
//i want now this token to be passed to Sb so i can then call its actions //without the need of the token
var result1=sb.Action1();
var result2=sb.Action2();
......
var resultN=sb.ActionN(); //<--
答案 0 :(得分:2)
正如注释中已经提到的那样,您可以创建一个工厂类,该工厂类将根据Sb
授予的令牌来创建Sa
的实例。
public interface ISbFactory
{
Sb Create();
}
public class SbFactory : ISbFactory
{
private readonly Sa _sa;
public SbFactory(Sa sa) => _sa = sa;
public Sb Create()
{
var token = _sa.GrantToken();
return new Sb(token);
}
}
用法
public class ConsumerOfSb
{
private readonly ISbFactory _sbFactory;
public ConsumerOfSb(ISbFactory sbFactory) => _sbFactory = sbFactory;
public void Execute()
{
var sb = _sbFactory.Create();
sb.ExecuteActionOne();
}
}
另一种方法:ASP.NET依赖项注入提供带有“工厂动作”的重载方法。因此,您可以注册一个函数,该函数将在每次需要Sb
实例作为依赖项时调用。
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient(sa);
services.AddTransient<Sb>(provider =>
{
var sa = provider.GetRequiredService<Sa>();
var token = sa.GrantToken();
return new Sb(token);
});
}
使用这种方法,Sb
的使用者不需要依赖工厂。
答案 1 :(得分:0)
我认为您可以在此处添加另一个抽象-例如Sb的抽象工厂。
public interface ISbFactory
{
SbFactory Create(string token);
}
现在依赖于Sb的客户端类应将其更改为ISbFactory。通过这种方法,您可以负责将令牌设置为出厂,而不是修改已经创建的服务。