.NET Core Singleton

0

Cześć,

w moim testowym projekcie mam sobie 3 klasy:

Program.cs, którego zadaniem jest konfiguracja singletonu:

public static IConfigurationRoot Configuration { get; set; }

     static void Main(string[] args)
     {
         Configuration = new ConfigurationBuilder()
         .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
         .AddCommandLine(args)
         .Build();

         var services = ConfigureServices();
         var serviceProvider = services.BuildServiceProvider();

         serviceProvider.GetService<App>().Run();
     }

     private static IServiceCollection ConfigureServices()
     {
         IServiceCollection services = new ServiceCollection();

         var config = LoadConfiguration();

         ConnectionString con = new ConnectionString();
         Configuration.Bind("ConnectionStrings", con);

         services.AddSingleton(config);
         services.AddSingleton(con);
         services.AddSingleton(Configuration);

         // required to run the application
         services.AddTransient<App>();

         return services;
     }

     public static IConfiguration LoadConfiguration()
     {
         var builder = new ConfigurationBuilder()
             .SetBasePath(Directory.GetCurrentDirectory())
             .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);

         return builder.Build();
     }

App.cs, która odpowiada za komunikacje z Userem (taka główna klasa aplikacji), mam tam taki konstruktor:


public App(IConfiguration config, ConnectionString con)
        {
            conf = config;

            var args = Environment.GetCommandLineArgs();

        }

I jest sobie też klasa FileService:

    public class FileService : File, IFile
    {
        private readonly ConnectionString con;

        public FileService(ConnectionString c) => con = c;

        public void GetFiles()
        {
            using (var connection = new SqlConnection(con.GetConnectionString()))
            {
                var procedure = "raporty_pobierz_pliki";
                var values = new { KoId = 200 };
                var results = connection.Query(procedure, values, commandType: CommandType.StoredProcedure).ToList();
                results.ForEach(r => Console.WriteLine($"{r.OrderID} {r.Subtotal}"));
            }
        }

        public void Save()
        {

        }
    }

Być może źle do tego podchodzę i czegoś nie rozumiem, ale chciałbym doprowadzić do sytuacji,w której, w FileService będę miał dane z singletona, którego dodałem tutaj: services.AddSingleton(con);. W jaki sposób to osiągnąć? Czy poprawnym rozwiązaniem jest przekazanie tego w konstruktorze gdy wywołuję klasę w App.cs new FileService(con).GetFiles();?

EDIT: Moje pytanie wiąże się też z tym, że chciałbym móc mieć dostęp z dowolnego miejsca aplikacji do drugiego singletonu, który przechowuje argumenty podane podczas uruchomienia aplikacji.

1

Coś tu namieszałeś. IConfiguration masz już za darmo dodane, więc nie dodajesz tego. Nie powinieneś też rejestrować innych swoich rzeczy.
Cała konfiguracja wczytuje Ci się automatycznie. Wystarczy, że będziesz wstrzykiwał do serwisów/kontrolerów IConfiguration. I tyle.

0

Dziękuję, pozbyłem się dodania IConfiguration i rzeczywiście działa.

Juhas napisał(a):

Coś tu namieszałeś. IConfiguration masz już za darmo dodane, więc nie dodajesz tego. Nie powinieneś też rejestrować innych swoich rzeczy.
Cała konfiguracja wczytuje Ci się automatycznie. Wystarczy, że będziesz wstrzykiwał do serwisów/kontrolerów IConfiguration. I tyle.

Dlaczego nie powinienem rejestrować swoich rzeczy?

1

Ale już istnieje obiekt implementujący interfejs IConfiguration, który ma CAŁĄ konfigurację, razem z connection stringami (jest metoda GetConnectionString), więc po co robić coś, co już jest? Zwłaszcza, że dodajesz jakieś 3 konfiguracje. To naprawdę jest mega dziwne i nie powinno się tak tego robić. Jeśli już musisz coś mieć w jakieś swojej klasie konfiguracyjnej, to poczytaj o IOptions

0
Juhas napisał(a):

Cała konfiguracja wczytuje Ci się automatycznie. Wystarczy, że będziesz wstrzykiwał do serwisów/kontrolerów IConfiguration. I tyle.

Mi wstrzykiwanie IConfiguration do kontrolerów/serwisów się nie podoba.
Dlaczego nie zrobić dedykowanych klas z opcjami/konfiguracją i do serwisów/kontrolerów wstrzykiwać tylko to co rzeczywiście tam jest potrzebne

1

A jaki jest w ogóle sens wstrzykiwania ConnectionString do globalnego rejestru serwisów? Po pierwsze i tak jest dostępny wszędzie przez IConfiguration, po drugie to jest przecież szczególik implementacji, nie element API żadnego modułu typu serwis, handler czy kontroler.

1
some_ONE napisał(a):
Juhas napisał(a):

Cała konfiguracja wczytuje Ci się automatycznie. Wystarczy, że będziesz wstrzykiwał do serwisów/kontrolerów IConfiguration. I tyle.

Mi wstrzykiwanie IConfiguration do kontrolerów/serwisów się nie podoba.
Dlaczego nie zrobić dedykowanych klas z opcjami/konfiguracją i do serwisów/kontrolerów wstrzykiwać tylko to co rzeczywiście tam jest potrzebne

No jest taki dedykowana klasa, IOptions<TOptions>:, która ładnie działa z IConfiguration, no ale ludzie nie potrafią czytać dokumentacji

0
somekind napisał(a):

A jaki jest w ogóle sens wstrzykiwania ConnectionString do globalnego rejestru serwisów? Po pierwsze i tak jest dostępny wszędzie przez IConfiguration, po drugie to jest przecież szczególik implementacji, nie element API żadnego modułu typu serwis, handler czy kontroler.

ConnectionString jest tylko przykładem. Równie dobrze mogły to być np. Logger. Czyli coś co ma być dostępne z każdego miejsca aplikacji.

2

No to bardzo nietrafiony przykład, bo ConnectionString to jest coś, co nie powinno być dostępne z każdego miejsca aplikacji.

0
somekind napisał(a):

No to bardzo nietrafiony przykład, bo ConnectionString to jest coś, co nie powinno być dostępne z każdego miejsca aplikacji.

W sumie masz racje, nie trafiłem z tym ConnectionStringiem ;)

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