Jak zdobyć aktualny IServiceScope?

Odpowiedz Nowy wątek
2019-12-29 14:35

Rejestracja: 17 lat temu

Ostatnio: 2 dni temu

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?

Pozostało 580 znaków

2019-12-29 20:51

Rejestracja: 3 lata temu

Ostatnio: 1 dzień temu

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.

Wrapper na Autofaca jest po to, żebym mógł wstrzykiwać IObjectFactory do klas typu CommandFactory. To mnie właśnie uwalnia od Service Locatora. - Juhas 2019-12-30 11:30
@Juhas: A bez wrappera mógłbyś wstrzyknąć IComponentContext, jaka różnica? - some_ONE 2019-12-30 13:31
Taka, że nie wszędzie używam Autofaca. W WebApi i WebApplication używam standardowego DI. - Juhas 2019-12-30 13:47

Pozostało 580 znaków

2019-12-30 08:21

Rejestracja: 7 lat temu

Ostatnio: 2 tygodnie temu

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

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

Pozostało 580 znaków

2019-12-30 11:33

Rejestracja: 17 lat temu

Ostatnio: 2 dni temu

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.

edytowany 1x, ostatnio: Juhas, 2019-12-30 13:48

Pozostało 580 znaków

Odpowiedz

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0