Изменить внедренный сервис по событию из другого сервиса - PullRequest
0 голосов
/ 17 января 2019

У меня следующая проблема:

У меня есть 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(); //<--

Ответы [ 2 ]

0 голосов
/ 21 января 2019

Как уже упоминалось в комментариях, вы можете создать фабричный класс, который будет отвечать за создание экземпляра 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 не нужно зависеть от фабрики.

0 голосов
/ 17 января 2019

Я думаю, что здесь вы можете добавить еще одну абстракцию - абстрактную фабрику для Sb, например:

    public interface ISbFactory
    {
        SbFactory Create(string token);
    }

Клиентские классы, которые теперь имеют зависимости от Sb, должны изменить его на ISbFactory. При таком подходе вы возлагаете ответственность за установку токена на фабрику вместо изменения уже созданного сервиса.

...