@@ -8,7 +8,7 @@ This implies that localizable resources are a part of domain model so they are s
88
99Prerequisites
1010-------------
11- DataObjects.Net 7.0 .x or later (http://dataobjects.net )
11+ DataObjects.Net 7.1 .x or later (http://dataobjects.net )
1212
1313Implementation
1414--------------
@@ -50,6 +50,7 @@ Define corresponding localizations, e.g.:
5050 }
5151```
5252
53+
5354Examples of usage
5455-----------------
5556
@@ -106,4 +107,264 @@ Examples of usage
106107 where p .Title == " Bienvenido"
107108 select p ;
108109 Assert .AreEqual (1 , query .Count ());
110+ ```
111+
112+
113+ Examples of how to configure extension
114+ --------------------------------------
115+
116+ Following examples show different ways to configure extension in configuration files of various types.
117+
118+ ** Example #1 ** Confugure in App.config/Web.config
119+
120+ ``` xml
121+ <configuration >
122+ <configSections >
123+ <section name =" Xtensive.Orm" type =" Xtensive.Orm.Configuration.Elements.ConfigurationSection, Xtensive.Orm" />
124+ <section name =" Xtensive.Orm.Localization" type =" Xtensive.Orm.Localization.Configuration.ConfigurationSection, Xtensive.Orm.Localization" />
125+ </configSections >
126+ <Xtensive .Orm>
127+ <!-- domain(s) configured -->
128+ </Xtensive .Orm>
129+ <Xtensive .Orm.Localization>
130+ <defaultCulture name =" es-ES" />
131+ </Xtensive .Orm.Localization>
132+ </configuration >
133+ ```
134+
135+ Such configuration is only compatible with System.Configuration.ConfigurationManager.
136+ If project still supports such configurations then Localization configuration will be read automatically when it needed to be read.
137+ Sometimes a work-around is needed to read such configuration, for more read Example #2 and Example #3
138+
139+
140+ ** Example #2 ** Reading old-style configuration of an assembly in NET 5 and newer.
141+
142+ Due to new architecture without AppDomain (which among the other things was in charge of gathering configuration files of loaded assemblies
143+ as it would be one configuration file) System.Configuration.ConfigurationManager now reads only configuration file of actual executable, loaded
144+ assemblies' configuration files stay unreachable by default, though there is need to read some data from them.
145+ A great example is test projects which are usually get loaded by test runner executable, and the only configuration accessible in this case
146+ is test runner one.
147+
148+ Extra step is required to read configuration files in such cases. Thankfully ConfigurationManager has methods to get access to assemblies' configurations.
149+
150+ To get access to an assembly configuration file it should be opened explicitly by
151+
152+ ``` csharp
153+ var configuration = ConfigurationManager .OpenExeConfiguration (typeof (SomeTypeInConfigOwnerAssembly ).Assembly .Location );
154+ ```
155+
156+ The instance returned from ``` OpenExeConfiguration ``` provides access to sections of the assembly configuration. DataObjects.Net configurations
157+ (``` DomainConfiguration ``` , ``` LocalizationConfiguration ``` , etc.) have ``` Load() ``` methods that can recieve this instance.
158+ ``` LocalizationConfiguration ``` can be read like so
159+
160+ ``` csharp
161+ var configuration = ConfigurationManager .OpenExeConfiguration (typeof (SomeTypeInConfigOwnerAssembly ).Assembly .Location );
162+ var localizationConfig = LocalizationConfiguration .Load (configuration );
163+
164+ // loaded configuration should be manually placed to
165+ domainConfiguration .ExtensionConfigurations .Set (localizationConfig );
166+ ```
167+
168+ The ``` domainConfiguration.ExtensionConfigurations ``` is a new unified place from which an extension will try to get its configuration
169+ instead of calling default parameterless ``` Load() ``` method, which has not a lot of sense now, though the method is kept as a second source
170+ for backwards compatibility.
171+
172+ For more convenience, DomainConfiguration extensions are provided, which make code more neat and clear.
173+ For instance,
174+
175+ ``` csharp
176+ var configuration = ConfigurationManager .OpenExeConfiguration (typeof (SomeTypeInConfigOwnerAssembly ).Assembly .Location );
177+
178+ var domainConfiguration = DomainConfiguration .Load (configuration );
179+
180+ // the extension hides getting configuration with LocalizationConfiguration.Load(configuration)
181+ // and also putting it to ExtensionConfigurations collection.
182+ domainConfiguration .ConfigureLocalizationExtension (configuration );
183+ ```
184+
185+ Custom section names are also supported if for some reason default section name is not used.
186+
187+
188+ ** Example #3 ** Reading old-style configuration of an assembly in a project that uses appsettings.json file.
189+
190+ If for some reason there is need to keep the old-style configuration then there is a work-around as well.
191+ Static configuration manager provides method ``` OpenMappedExeConfiguration() ``` which allows to get
192+ any * .config file as ``` System.Configuration.Configuration ``` instance. For example
193+
194+ ``` csharp
195+ ExeConfigurationFileMap configFileMap = new ExeConfigurationFileMap ();
196+ configFileMap .ExeConfigFilename = " Orm.config" ; // or other file name, the file should exist bin folder
197+ var configuration = System .Configuration .ConfigurationManager .OpenMappedExeConfiguration (configFileMap , ConfigurationUserLevel .None );
198+ ```
199+
200+ After that, as in previous example, the instance can be passed to ``` Load ``` method of ``` LocalizationConfiguration ``` to read extension configuration
201+ and later put it to ``` DomainConfiguration.ExtensionConfigurations ``` .
202+ After ``` System.Configuration.Configuration ``` instance is provided it is possible to pass it into Load method of different DataObjects.Net configurations,
203+ including ``` LocalizationConfiguration ``` . Then put localization configuration to ``` DomainConfiguration.ExtensionConfigurations ``` collection.
204+
205+ ``` csharp
206+ var localizationConfiguration = LocalizationConfiguration .Load (configuration );
207+
208+ domainConfiguration .ExtensionConfigurations .Set (localizationConfiguration );
209+ ```
210+
211+ or to extension method
212+
213+ ``` csharp
214+ domainConfiguration .ConfigureLocalizationExtension (configuration );
215+ ```
216+
217+
218+ ** Example #4 ** Configure using Microsoft.Extensions.Configuration API.
219+
220+ This API allows to have configurations in various forms including JSON and XML formats.
221+ Loading of such files may differ depending on .NET version, check Microsoft manuals for instructions.
222+
223+ Allowed Json and Xml configuration definition look like below
224+
225+ ``` xml
226+ <configuration >
227+ <Xtensive .Orm.Localization>
228+ <DefaultCulture >es-ES</DefaultCulture >
229+ </Xtensive .Orm.Localization>
230+ </configuration >
231+ ```
232+
233+ ``` json
234+ {
235+ "Xtensive.Orm.Localization" : {
236+ "DefaultCulture" : " es-ES"
237+ }
238+ }
239+ ```
240+
241+ The API has certain issues with Xml elements with attributes so it is recommended to use
242+ more up-to-date attributeless nodes.
243+ For JSON it is pretty clear.
244+
245+ ``` LocalizationConfiguration.Load ``` method can accept different types of abstractions from the
246+ API, including
247+ - ``` Microsoft.Extensions.Configuration.IConfiguration ``` ,
248+ - ``` Microsoft.Extensions.Configuration.IConfigurationRoot ```
249+ - ``` Microsoft.Extensions.Configuration.IConfigurationSection ``` .
250+
251+ Loading of configuration may look like
252+
253+ ``` csharp
254+
255+ var app = builder .Build ();
256+
257+ // tries to load from default section "Xtensive.Orm.Localization"
258+ var localizationConfig = LocalizationConfiguration .Load (app .Configuration );
259+
260+ domainConfiguration .ExtensionConfigurations .Set (localizationConfig );
261+ ```
262+
263+ or, with use of extension
264+
265+
266+ ``` csharp
267+
268+ var app = builder .Build ();
269+
270+ // tries to load from default section "Xtensive.Orm.Localization"
271+ // and additionally adds Xtensive.Orm.Localization assembly to domain types.
272+
273+ domainConfiguration .ConfigureLocalizationExtension (app .Configuration );
274+ ```
275+
276+
277+
278+ ** Example #5 ** Configure using Microsoft.Extensions.Configuration API from section with non-default name.
279+
280+ For configurations like
281+
282+ ``` xml
283+ <configuration >
284+ <Orm .Localization>
285+ <DefaultCulture >es-ES</DefaultCulture >
286+ </Orm .Localization>
287+ </configuration >
288+ ```
289+
290+ ``` json
291+ {
292+ "Orm.Localization" : {
293+ "DefaultCulture" : " es-ES"
294+ }
295+ }
296+ ```
297+
298+ Loading of configuration may look like
299+
300+ ``` csharp
301+
302+ var app = builder .Build ();
303+
304+ var localizationConfig = LocalizationConfiguration .Load (app .Configuration , " Orm.Localization" );
305+
306+ domainConfiguration .ExtensionConfigurations .Set (localizationConfig );
307+ ```
308+
309+ or with use of extension
310+
311+ ``` csharp
312+
313+ var app = builder .Build ();
314+
315+ domainConfiguration .ConfigureLocalizationExtension (app .Configuration , " Orm.Localization" );
316+ ```
317+
318+
319+ ** Example #6 ** Configure using Microsoft.Extensions.Configuration API from sub-section deeper in section tree.
320+
321+ If for some reason extension configuration should be moved deeper in section tree like something below
322+
323+ ``` xml
324+ <configuration >
325+ <Orm .Extensions>
326+ <Xtensive .Orm.Localization>
327+ <DefaultCulture >es-ES</DefaultCulture >
328+ </Xtensive .Orm.Localization>
329+ </Orm .Extensions>
330+ </configuration >
331+ ```
332+
333+ or in JSON
334+
335+ ``` json
336+ {
337+ "Orm.Extensions" : {
338+ "Xtensive.Orm.Localization" : {
339+ "DefaultCulture" : " es-ES"
340+ }
341+ }
342+ }
343+ ```
344+
345+ Then section must be provided manually, code may look like
346+
347+ ``` csharp
348+
349+ var app = builder .Build ();
350+
351+ var configurationRoot = app .Configuration ;
352+ var extensionsGroupSection = configurationRoot .GetSection (" Orm.Extensions" );
353+ var localizationSection = extensionsGroupSection .GetSection (" Xtensive.Orm.Localization" );
354+ var localizationConfig = LocalizationConfiguration .Load (localizationSection );
355+
356+ domainConfiguration .ExtensionConfigurations .Set (localizationConfig );
357+ ```
358+
359+ or with use of extension method
360+
361+ ``` csharp
362+
363+ var app = builder .Build ();
364+
365+ var configurationRoot = app .Configuration ;
366+ var extensionsGroupSection = configurationRoot .GetSection (" Orm.Extensions" );
367+ var localizationSection = extensionsGroupSection .GetSection (" Xtensive.Orm.Localization" );
368+
369+ domainConfiguration .ConfigureLocalizationExtension (localizationSection );
109370```
0 commit comments