C# 根据来自另一个服务的事件修改注入的服务
我有以下问题: 我有C# 根据来自另一个服务的事件修改注入的服务,c#,asp.net-core,dependency-injection,C#,Asp.net Core,Dependency Injection,我有以下问题: 我有2服务:SaSb为了让用户能够使用Sb他需要在Sa中执行一个动作,该动作将授予他一个令牌 然后,他将使用此标记执行他将对Sb执行的所有操作 我不希望Sb的所有方法都需要token作为参数。我希望从一开始就将Sb注入servicecollection中,并能够将该token作为内部属性存储(在用户使用Sa之后) 我该怎么做?如何根据另一个服务中的操作更改注入的服务 授予令牌的服务 public class Sa{ //grants token public st
2
服务:Sa
Sb
为了让用户能够使用
Sb
他需要在Sa
中执行一个动作,该动作将授予他一个令牌
然后,他将使用此标记
执行他将对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(); //<--
var-token=sa.GrantToken();
//现在我想把这个令牌传递给Sb,这样我就可以调用它的动作//而不需要令牌
var result1=sb.Action1();
var result2=sb.Action2();
......
var resultN=sb.action()// 我认为你可以在这里添加另一个抽象概念——抽象工厂
public interface ISbFactory
{
SbFactory Create(string token);
}
现在依赖于Sb的客户端类应该将其更改为ISbFactory。使用这种方法,您将负责将令牌设置为工厂,而不是修改已创建的服务。我认为您可以在此处添加另一个抽象-例如为Sb抽象工厂
public interface ISbFactory
{
SbFactory Create(string token);
}
现在依赖于Sb的客户端类应该将其更改为ISbFactory。使用这种方法,您将负责将令牌设置为工厂,而不是修改已创建的服务。如注释中所述,您可以创建一个工厂类,该类将负责根据Sa
授予的令牌创建Sb
的实例
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);
}
}
用法
另一种方法: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);
});
}
public void配置服务(IServiceCollection服务)
{
服务部(sa);
services.AddTransient(提供者=>
{
var sa=provider.GetRequiredService();
var token=sa.GrantToken();
归还新的某人(代币);
});
}
使用这种方法,Sb
的消费者不需要依赖工厂 如评论中所述,您可以创建一个工厂类,该类将负责根据Sa
授予的令牌创建Sb
的实例
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);
}
}
用法
另一种方法: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);
});
}
public void配置服务(IServiceCollection服务)
{
服务部(sa);
services.AddTransient(提供者=>
{
var sa=provider.GetRequiredService();
var token=sa.GrantToken();
归还新的某人(代币);
});
}
使用这种方法,Sb
的消费者不需要依赖工厂 您需要一个sb工厂,该工厂使用从saThat创建的令牌创建实例,或者在调用依赖成员之前在sb上设置令牌。您需要一个sb工厂,该工厂使用从saThat创建的令牌创建实例,或者在调用依赖成员之前在sb上设置令牌,这意味着使用的所有类ISbFactory
需要依赖于Sa
才能检索用于创建Sb
实例的令牌。是的,在此实现中。您可以随时更改术语以创建()并将Sa注入工厂实现。通过这种方式,您封装了创建令牌的逻辑。然而,正确的选择取决于问题的详细信息。这意味着所有使用ISbFactory
的类都需要依赖Sa
来检索用于创建Sb
实例的令牌。是的,在这个实现中。您可以随时更改术语以创建()并将Sa注入工厂实现。通过这种方式,您封装了创建令牌的逻辑。然而,正确的选择取决于问题的细节。比如工厂委托方法。很好的建议。像工厂代表的方法。好建议。