Jak zdobyć aktualny IServiceScope?

0

Hej, krótkie pytanie:

Krótkie pytanie
Gdy używam domyślnego DI w .netcore, jak dostać się do aktywnego IServiceScope, żeby móc ręcznie za pomocą GetService pobrać serwis?

Wyjaśnienie dla dociekliwych po co mi to
Mam solucję, która składa się z 30 projektów. Wśród nich są klienci: WPF, Xamarin, WebApplication(MVC), a także WebAPI.
Generalnie system jest tak pomyślany, żeby można było napisać jak najwięcej klientów pod różne systemy i żeby jak największa ilość kodu mogła być użyta ponownie.

I teraz tak. System zawiera komendy (polecenia) - po prostu klasy, które implementują odpowiedni interfejs.
System zawiera też CommandFactory, który w skrócie wygląda tak:

public class CommandFactory: ICommandFactory
{
    IObjectFactory objFactory; //this is my DI container

    public CommandFactory(IObjectFactory objFactory)
    {
        this.objFactory = objFactory;
    }

    public T CreateCommand<T>() where T: IExecutableCommand
    {
        return objFactory.Resolve<T>();
    }
}

Żeby to działało, potrzebuję czegoś w rodzaju własnego kontenera IOC (tutaj - IObjectFactory). Tak naprawdę dla większości klientów mam po prostu jednego "wrappera" na Autofac.
Jednak przy WebApplication używam standardowego IOC dla .netcore. I tu pojawia się problem. O ile w innych klientach wszystko działa poprawnie, to WebApplication jest zupełnie innym tworem i powoduje problemy.

Do tej pory w tym wrapperze IOC do webApplication, w taki sposób pobierałem serwis zarejestrowany jako scope:

class WebIocContainer: IObjectFactory //to singleton
{
    IServiceProvider serviceProvider; //to ustawiam w Startup


    public T Resolve<T>()
    {
       using(var scope = serviceProvider.CreateScope())
       {
           return scope.ServiceProvider.GetRequiredService<T>();
       }
    }
}

Oczywiście bardzo szybko okazało się, że to nie tak. W tym momencie tworzę nowy scope, który nie ma żadnych instancji. Więc wszystkie obiekty są tworzone od nowa, tak jakby były zarejestrowane jako Transition. A tego nie chcę.

Więc stąd pytanie - jak pobrać aktualny IServiceScope, żeby móc z niego pobrać serwisy?

0

Nie do końca rozumiem czemu utworzyłeś wrapper na Autofaca? Wygląda to na takiego Service Locator'a, który w tym przypadku raczej jest zbędny.
IExecutableCommand pewnie leżą gdzieś w osobnych projektach a w poszczególnych aplikacjach klienckich chciałbyś je używać tak? Jeśli tak, to tam gdzie są komendy utworzyłbym moduł autofac z rejestracją. A same aplikację klienckie wpf, xamariny itd. tylko muszą zawołać ich rejestrację. Następnie autofac czy to dla kontrolerów mvc, web api i pewnie też xamarin'a już sam się zajmie wstrzykiwaniem tych komend.

1

HttpContext ma property RequestServices więc jeśli masz obiekt HttpContext możesz zrobić tak:

var resolved = context.RequestServices.GetService<MyService>();
0
bfraszczyk napisał(a):

HttpContext ma property RequestServices więc jeśli masz obiekt HttpContext możesz zrobić tak:

var resolved = context.RequestServices.GetService<MyService>();

Wszystko byłoby super, gdyby mój IObjectFactory nie był rejestrowany jako singleton :D
Podejrzewam, że wstrzyknięcie IHttpContextAccessor do singletona nic mi nie da, prawda?

Jednak poniekąd dajesz mi odpowiedź, tylko to wymaga ode mnie pewnej zmiany w CommandFactory. Musiałbym utworzyć klasę bazową i dwie klasy CommandFactory - jedną dla WebApplication, drugą dla reszty.

[Edit]
CommandFactory zostawię tak jak jest. Zrobię nowy ObjectFactory, bo i tak dla WebApplication mam inny. I tutaj będzie już mógł być zarejestrowany jako scope.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.