ā best way to store and handle Settings/Config of an app
I realized a little tool and I'd like to create a Settings/Configuration system for store some info, example I have several
and I'd like to put them in a .ini or whatever file, so I can edit them without having to edit the source code
I found few packages I think could works for the purpose:
Serilog.Settings.Configuration
215.4M downloads
Microsoft.Extensions.Configuration.Ini
47.6M downloads
I don't know if they are good and if there exist better stuffs105 Replies
serilog is a logging library, so thats not really relevant here.
M.E.C
is however a configuration library that does pretty much exactly what you wanthow are these settings intended to be updated?
just by updating a file? with some sort of UI?
M.E.C does not work well for the latter
in this case I expect to open this file with notepad and edit it, just for avoid to having to change the source and recompile everytime
I thought something like this (crystaldisk sample)
but this morning I read on the web about appsettings.json
it seems like something already exist so in this case I'd just have to implement it, in web apps it's autogenerated, but not in consoleapps
oh, I think we're talking about the same thing
Microsoft.Extensions.Configuration.Json
good news,
appsettings.json
in ASP.NET uses M.E.C
š
yes
its very easy to get it going in console apps toonot I install it and I try
Microsoft.Extensions.Configuration.Ini exists btw
oh, very nice
https://www.nuget.org/packages?q=Microsoft.Extensions.Configuration&frameworks=&tfms=&packagetype=&prerel=true&sortby=relevance
I'm checking there, what does the first pack do? it's called just Microsoft.Extensions.Configuration
thats the base functionality
you will need that
the .ini one just adds support for reading ini files
so if I install Microsoft.Extensions.Configuration.Json it will install also Microsoft.Extensions.Configuration
yes
ok just installed
I don't see the base one, should I install it manually?
no, you dont need to explicitly add the base one
unless you need to pin its version
(which you probably dont want to do)
ok
I now created an appsettings.json is it normal I see this and I can just clean it or there's an existing model I can add?
maybe this one? .settings
uhm
you dont write C# code in a json file :p
thats a "blank" settings file in json
ok
I just found this on google, maybe it's a predefined model, there is Json and Json Schema
there is no predefined model
and you dont want a scehma file
those are something different
ok
perfect, I created an empty json and setted it as "Copy to Output Directory"
good
š
I followed this sample with sample data and it seems to works
about this:
are there better forms? I noticed I have to pass this
"ConnectionString:SqlServer"
as a string, I mean, the compiler don't give me hints about existings parameters in appsettings.json, example, if I type Conn it does not autocompletecorrect
thats the most basic form of doing it
M.E.C contains a few optional ways of binding your configuration to an object
found this also, but I think the first one is prettier
Microsoft.Extensions.Configuration.Binder
to use this, you make a class that has the same structure as your settings
and then you can access it like sooh cool, in this way I don't have to remember exact parameter names
is EnvironmentVariables necessary too?
I'm liking this very much, I made some Angular tasks many days ago but I literally lost my head for very easy stuffs, and ppl say Angular is easier than C#
if you want to access environment variables as part of your configuration, yes. if not, no
ok
can I store bool values? I removed
"
quotes around true
obviously in the json file, like this
but when I type
it says cannot convert string to bool, but I removed quotes š§yes
well, you can't access it via that way
but you can via the binding
oh ok :/
the next thing I want to do is to integrate a logging library like this or the microsoft one, I guess is
Microsoft.Extensions.Logging
I never used a logging library, also in this case, as a consoleapp, I putted many Console.WriteLine(""); for type what's happening and what I'm doing, additionally I can just save those prints in a .log file generated like me
does Serilog make the same thing or what?Serilog is the king of logging frameworks
if you want, you can develop with M.E.L and add the serilog adapter that "combines" them, but imho just go for serilog directly
serilog works around structured logging events and multiple "sinks"
so you can have a file sink that writes logs to file, and ALSO have a console sink that prints to the console
and later add in a SEQ sink, or ELK, or whatever log aggregator you like
M.E.L. have more downloads but anyway as I never used them idk which is better
serilog
ok
MEL is used by all official MS stuff, thats why it has so many downloads
and its not bad, just doesnt have nearly as much features as serilog
I'm reading some samples but I don't fully understand what does this serilog do, this is a sample from their official website
isn't just almost the same thing that I do with Console.WriteLine?
yeah it add date and hour before, and colors, but as I'm understanding I have to manually write what to print
yes, of course
if you didnt tell it what to write, how would it know? š
the benefit of this is that one, that data is structured. its not just a string
couldn't I achieve the same by adding something like DataTime.Now at the beginning?
and also that you can easily configure this to store the data in a file AND print it to the console
uh.. no?
that would just add time info to the string you are only writing to a console
here is a serilog demo I had lying around
this will log to a file and print to the console, all configured in a single location. It will add log level and timestamp information.
so benefits are:
- log level (debug, information, warning... etc)
- time
- automatic log to file
its way more than that, but thats some of it
well it seems nice, so all I should to after installing it is to replace all Console.WriteLine with log.
its easy to use, and configured in one place only. that means you dont need to update every place you call your log function if you decide to change how you do things
yep, thats the first step
well why don't do it^^ not I try
I never understood a thing, if I install the first one am I including all others?
I guess I need the third instead
Serilog.Extensions.Logging
a sample I found online only use those 2:
no, the first one is the base
it wont include any other
but
Serilog.Sinks.File
will include base serilog
you need the sinks you want, most likely File and Consoleok, so Sinks.File is for log to a file
yup
if the console logging is included in the base why they created Serilog.Extensions.Logging ?
its not included in the base
S.E.L
is the adapter library that makes it work with M.E.L
ohh ok
I think a similar thing
you could read the description on the packages
Serilog.Settings.Configuration
Microsoft.Extensions.Configuration (appsettings.json) support for Serilog
yesterday I thought it was something like M.E.C realized by Serilog authorso I guess I need those 2
yup.
I assume this is an old sample, this made both by only including .Sinks (or maybe he installed both and included all .Sinks "sublevels"
packages and namespaces are not 1-1 correlated
so
Serilog.Sinks.Console
doesnt actually need a using Serilog.Sinks.Console;
at the top to work
it adds an extension method on the Log.WriteTo
objectso you are telling me that this:
is the same of:
no
Im not
oh ok now I und
Im saying that a package name has no impact on the namespaces it can declare objects in
so it's plausible that this dude had
Serilog.Sinks.Console
installed but he didn't added the namespace since it's not supposed to be addedcorrect.
thats the full code from this file
it uses both Sinks.File and Sinks.Console, as you can see
I'm twisted now :/ like when you find out Santa does not exists
well you clearly had an incorrect understanding of what namespaces are and how they work :p
all I knew about namespaces is that they're just an alias definer or an object and they need to be included with
using
in order to use its objects or part of them
till now I always used this approach when didn't know which pack install
writing this
so VisualStudio tell me which pack install for correct the error š¦no
VS wont tell you what to install, it will tell you what references you need
but that only works for things already in the solution, or BCL classes iirc
it wont recommend third-party nugets
ok
ok just tried it on my skin š¤£
it recommend me to install only
Serilog
it solve the error red line under log. but it doesn't print stuffs since I had to install Sinks.Console and instantiate it with LoggerConfiguration()
it works like a charm
which name could be elegant for a .log file?
could using myapp.log be pretty?you shouldn't have a
using
on that
or well, you might be able to get away with it, depends on where that code is
but in general, dont - its just disposing the loggerok
obs studio log files just use the dates without putting a prefix
just one thing, but I think it could not be solved with 1 row, looks like I can't space messages like I used to do with cw
should I add 1 blank cw row for create a space?
you shouldn't
these are log messages, you shouldn't care about how they look in the console
adding a blank line like that will make that individual log message weird
I'd like to add a blank line for a better view, cause my tool run many cmd commands, that generated their-self many many rows, and I want to separate those generated blocks from the next log message
I suppose that if I want to use this library for log all eventual errors I'd have to spam try-catch statements everywhere
probably yes.
you usually also set a catch-all try/catch at the top level, to log any fatal crashes that reach that point
but it should ideally never trigger
but you misunderstand the purpose of a logger if you are worrying about how the output looks
at the top level? oh you mean to put the whole code into an unique try catch
yeah, more or less.
ok
many time ago, when I discovered try-catch statement, I started to spam it every where, like 10-20 times at once for being able to print every possible error, but after a while I read that it's not a good thing to do since I should predict and handle possible errors
https://coderr.io/exception-handling
Best practice number 1: do not catch exceptions. Let's start by defining what "handled" means when talking about exceptions.
yep
or rather
best practice number 1: write code so that it doesnt throw exceptions for most cases
exceptions should be exceptional
if you try to delete a file and get a
FileNotFoundException
, you as a developer fucked up
you should have checked that the file existed before trying to delete it
or maybe there is a TryDeleteFile
method that doesnt throw, if you dont careyeah about this I found a sample online that do this
but which is the sense to throw an exception? the program will crash anyway
generally you throw an exception when you cant handle it locally
perhaps you cant show the user an error here, because this is a library
and you dont know if the user is an actual human using a GUI or this is a webserver
so you throw and let the caller handle it
hm, I'll elaborate better this concept in the future, seems abstract for now
I'm just assuming that the logger can't be used into other functions that I call from Main()
I could replicate this block of code into other functions but I think this will going to generate another file
many years ago when I was using VB.NET I used to solve those kind of problems by putting those declarations out of all, immediately after class opening, but this can't be done here xD
it can. usually, you would access it via dependecy injection
but serilog also offers a static logger
so instead of
using var log...
write Log.Logger =
and you can now globally access that via Log.
oh, now I und why people put Serilog inizialitation into another .cs or into another project of the solution
the code is cleaner and they can call it from everywhere
which solution is better? I guess the DI one
I prefer DI, since it lets me mock the logger for tests
in this sample I found theres also a .ReadFrom.Configuration(cb) but it's not explained what does it do and only there are no other file available to read
but I guess the content is log level, if writetofile, if writetoconsole etc
mock the logger?
unfortunately I don't understand DI yet, but on the web people say is easy to use and used by tons of coders as utility stuff
from what I see this DI seems simple, typing few lines of code should be enough but I feel that I'd do it mechanically, which are requirements in terms of knowledge for understand DI? knowing interfaces?
yes and no
interfaces are extremely common, but not actually part of DI itself
If you just want a quick idea of what it is and how it works, I recommend this video (that I made) on the topic: https://www.youtube.com/watch?v=USBoZtGt0QU
I solved in this way (there are more ways to convert to bool, I used this one)
I would suggest you learn to use the model binding approach
yeah I'll try to use binding anyway like I prefer that the compiler suggest me variables
you will need
Microsoft.Extensions.Configuration.Binder
installedok
I make some improvements to the code then I'll make this one also as sort of improvement.
Next steps will be to learn Interfaces, since I assumed they're very common, and I can't continue ignore them, and after maybe try to understand DI if not early
interfaces are fairly simple
its a contract that a class MUST adhere to if they want to "implement" that interface
I seen an YT video about interfaces, and it explained Interfaced are a sort of Inheritance (concept that I mastered theoretically but never practised)
thus you can safely use the methods from the interface without knowing the concrete type
eh, it uses the same syntax as inheritance but Im not sure if it actually is inheritance under the surface
the guys of the YT tutorial made a similitude like:
Inheritance: a child take parents eyes
Interface: a child learn the parent job
converter
here is of type IStringToIntConverter
meaning we can only access the methods that interface describesWas this issue resolved? If so, run
/close
- otherwise I will mark this as stale and this post will be archived until there is new activity.