Suppose there are two tables in the database: the first table contains columns

Id, Alias, Title 

and it has entries:

 1 | "SiteSettings" | "Настройки сайта", ... 

the second table contains columns

 Id, ParentId, Alias, Title, Value, ValueType 

the contents of the table view:

 1 | 1 | "AllowRegistration" | "Разрешить регистрацию" | "True", "System.Boolean", ... 

At the start of the application, a static cache is formed, a variable is added to it

 dynamic Settings 

(Maybe something else should be used instead of dynamic?)

Well, actually the question itself: Is it possible to get something like this at the output:

 Settings.SiteSettings.AllowRegistration 

And if so, how?

  • > Perhaps, instead of dynamic, something else should be used - yes, in this case it is worth using the usual strictly typed classes - PashaPash

3 answers 3

Despite the fact that in this case, you can use dynamic , a more reliable way would be to declare two normal classes, Settings and SiteSettings .

dynamic should be used only when it is painfully painful to write code without them:

  • work with COM
  • interaction with dynamic languages ​​(for example, with IronPython)

If in a specific case, instead of dynamic you can create a specific class, then you should create it.

  • The trouble is that it is not known in advance what the settings are in the database, but it would be nice to work with them as with the ViewBag for example. - Dmitry
  • I mean, I mean that the construction of the Settings.SiteSettings.AllowRegistration view should turn out dynamically - Dmitry
  • @Dmitry if you do not know in advance what settings you have, then you cannot mention them in the code as Settings.SiteSettings.AllowRegistration . And if you still know in advance (at the time of writing the code) that there is a setting for SiteSettings.AllowRegistration - what's stopping you from using a regular class? - PashaPash
  • @Dmitry I mean, if you need to access the settings in the code in the form of the Settings.SiteSettings.AllowRegistration string, you do not need the speakers. enough of the usual Dictionary<string, object> . - PashaPash
  • This will be a separate Dll code that will not be transmitted to outsourcers, but an outsource layout designer, for example, could use a normalized view and not gineriki. Actually, the idea is that someone has created the settings through the admin area, and the layout designer has easily applied it - Dmitry
 dynamic settings= new ExpandoObject();; settings.SiteSettings= new ExpandoObject(); settings.SiteSettings.AllowRegistration = false 
  • Probably the question is not correctly understood, the design of settings.SiteSettings.AllowRegistration is not known in advance, I would like to have it dynamically - Dmitry

The solution was found on the expanses of the English-language resource stack:

first we do an extension for ExpandoObject :

 public static class ExpandoExt { public static KeyValuePair<string, object> WithValue(this string key, object value) { return new KeyValuePair<string, object>(key, value); } public static ExpandoObject Init(this ExpandoObject expando, params KeyValuePair<string, object>[] values) { foreach (KeyValuePair<string, object> kvp in values) { ((IDictionary<string, Object>)expando)[kvp.Key] = kvp.Value; } return expando; } } 

Further:

 using (var repo = new SettingRepository()) { IList<KeyValuePair<string, object>> obj = new List<KeyValuePair<string, object>>(); foreach (var section in repo.Collection) { obj.Add(new KeyValuePair<string, object>(section.Alias, section.Value)); } _settings = ((ExpandoObject)_settings).Init(obj.ToArray()); } 

and voila, the construction _settings.чего-то_там_из_базы works. maybe someone else will need a link to English sabzh

UPD : in practice, everything can be reduced to a design:

 ... foreach (var section in repo.Collection) { ((IDictionary<string, object>)_settings)[section.Alias]=section.Value; } ...