Before starting the application, it is necessary to initialize the array List<List<string>> values ​​from an external source. What is the most “correct” way to do this? Use xml file and serialization / deserialization, text file or are there more beautiful "traditional" settings storage solutions?

  • one
    Settings have not tried? - VladD
  • It's kind of like storing interface settings in winforms applications - e1s
  • What settings are we talking about? Can you more accurately describe why this list of strings is needed? The size of it? Where does it come from? Why is it used? Does it change? - Pavel Hritonenko
  • There was already a similar question. Stackoverflow.com/questions/462188/… By the way, from you - Dmitry
  • @PavelHritonenko does not change, it is necessary to fill the array as quickly as possible with lines from the file and pass to the method - e1s

2 answers 2

The correct Microsoft recommended path is storing data in Settings . The only subtlety - in the Settings not easy to insert non-scalar data.

We act as follows:

  1. Go to the project properties, Settings tab.

    Settings not created

  2. We create Settings by default, we put in it property ListOfListsOfStrings . As a type, we cannot select List<List<string>> , therefore we temporarily select just string .

    Created one property

  3. Close the project (important!), Go to the project directory, open the file Properties\Settings.settings text editor. Find a string like

     <Setting Name="ListOfListsOfStrings" Type="System.String" Scope="User"> 

    we drive the right type

     <Setting Name="ListOfListsOfStrings" Type="System.Collections.Generic.List&lt;System.Collections.Generic.List&lt;System.String&gt;&gt;" Scope="User"> 

    Because we are editing XML, we need to encode < and > like &lt; and &gt; .

    Hack through a text editor

  4. Close the editor, reopen the project. We find the Settings.settings file in the Properties directory in the project, select the Run custom tool from the context menu to regenerate Settings.Designer.cs .

    Regenerate designer.cs

  5. The project must compile. Add the code that will work with Settings :

     static void Main(string[] args) { var settings = ListListSettings.Properties.Settings.Default; // при первом пробеге тут ничего нет, создаём if (settings.ListOfListsOfStrings == null) { settings.ListOfListsOfStrings = new List<List<string>>() { new List<string>() { "1", "2" }, new List<string>() { "3", "4", "5" } }; settings.Save(); } } 

Everything!


Update: instead of the logic of setting the initial value in Main you can write this very initial value in Settings.settings . To do this, you need to specify the following string as the initial value in the Settings tab:

 <?xml version="1.0" encoding="utf-16"?> <ArrayOfArrayOfString xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <ArrayOfString> <string>1</string> <string>2</string> </ArrayOfString> <ArrayOfString> <string>3</string> <string>4</string> <string>5</string> </ArrayOfString> </ArrayOfArrayOfString> 

It needs to be copied into the Value input field, rather than trying to manually write to the Settings.settings file, because the < and > values ​​in the file need to be changed to &lt; and &gt; . It should turn out something like this:

menus and buttons

Where to get such a tricky line? Do not invent it yourself? In fact, it can be found by adding this code:

 var sample = new List<List<string>>() // это тот список, который мы раньше { // записывали в settings.ListOfListsOfStrings new List<string>() { "1", "2" }, new List<string>() { "3", "4", "5" } }; var xs = new XmlSerializer(sample.GetType()); using (var sw = new StringWriter()) { xs.Serialize(sw, sample); var serialized = sw.ToString(); // (*) } 

At the point marked with an asterisk, look at the value of the serialized variable through the debugger - there will be exactly what you need:

visualizer selection from here you can copy

Given the changes, the program code is simplified to this:

 static void Main(string[] args) { var settings = ListListSettings.Properties.Settings.Default; var listOfList = settings.ListOfListsOfStrings; } 

@Pavel Mayorov, thanks for the help in the comments.

  • Thanks, I will try - e1s
  • @ e1s: Please! - VladD
  • Instead of the complex logic of setting the default values, you could set it in Settings - Pavel Mayorov
  • @PavelMayorov: Yeah, right. Then I did not figure out how to do it. Now I will add. - VladD
  • @PavelMayorov: Hmm, for some reason I don’t come out, and you? - VladD

A very convenient storage option for almost any settings is offered by the FSharp.Configuration project.

There are several main advantages of using this approach, regarding the method proposed by @VladD:

  1. Settings will be strictly typed - the types of settings will be checked at compilation. This means that the type with the settings will be "created" when compiled according to the structure of the default config. That is, the numbers - will be int 's, 00:50:00 - will turn into a TimeSpan , etc.
  2. You can use the Yaml format - which is understandable, clean, supports out-of-the-box collections.
  3. No need to load and unload a project
  4. If you don’t "cache" the value of a member in a local variable, then when accessing Settings.SomeList , we will always have the current value (the static instance will monitor the file and reread its contents).

An example of using C # is on the provider page .

  • Cool, did not know. And what is different from the standard Settings except for the storage format? - VladD
  • @VladD after using this library, the standard Settings seem somehow unreasonable. In addition, FSharp.Configuration supports several formats - AppSettings, ResX, Ini, Yaml. - Pavel Hritonenko
  • Regarding the differences: in the standard version, the settings are also strongly typed. The internal format in theory is not interesting to anyone, the abstraction - put the data, took the same when restarting the application. - VladD 2:51
  • Regarding clause 4, this does not seem to me a serious advantage: the semantics of Settings does not imply the user's knowledge of where and how they are stored, not to mention its active change. Moreover, it is not clear what to do with the half-recorded data - race condition? But the third point - an undoubted fat plus. - VladD
  • one
    @VladD added, although it is not important in the context of the storage List<List<string>> . Well, in this case we are not talking about "code generation", we are talking about class generation at the compilation stage - the TypeProviders mechanism is used. - Pavel Hritonenko