subsonic 3.0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. data/lib/LICENSE.txt +41 -0
  2. data/lib/SubSonic.Core.dll +0 -0
  3. data/lib/T4 Templates/ActiveRecord/ActiveRecord.tt +620 -0
  4. data/lib/T4 Templates/ActiveRecord/Context.tt +295 -0
  5. data/lib/T4 Templates/ActiveRecord/SQLServer.ttinclude +347 -0
  6. data/lib/T4 Templates/ActiveRecord/Settings.ttinclude +552 -0
  7. data/lib/T4 Templates/ActiveRecord/StoredProcedures.tt +30 -0
  8. data/lib/T4 Templates/ActiveRecord/Structs.tt +67 -0
  9. data/lib/T4 Templates/LinqTemplates/Classes.tt +117 -0
  10. data/lib/T4 Templates/LinqTemplates/Context.tt +276 -0
  11. data/lib/T4 Templates/LinqTemplates/SQLServer.ttinclude +349 -0
  12. data/lib/T4 Templates/LinqTemplates/Settings.ttinclude +551 -0
  13. data/lib/T4 Templates/LinqTemplates/StoredProcedures.tt +30 -0
  14. data/lib/T4 Templates/LinqTemplates/Structs.tt +67 -0
  15. data/lib/T4 Templates/README.txt +7 -0
  16. data/lib/T4 Templates/SubSonic.TemplatesVB/ActiveRecord/ActiveRecord.tt +560 -0
  17. data/lib/T4 Templates/SubSonic.TemplatesVB/ActiveRecord/ActiveRecord.vb +6447 -0
  18. data/lib/T4 Templates/SubSonic.TemplatesVB/ActiveRecord/Context.tt +258 -0
  19. data/lib/T4 Templates/SubSonic.TemplatesVB/ActiveRecord/Context.vb +349 -0
  20. data/lib/T4 Templates/SubSonic.TemplatesVB/ActiveRecord/SQLServer.ttinclude +332 -0
  21. data/lib/T4 Templates/SubSonic.TemplatesVB/ActiveRecord/Settings.ttinclude +550 -0
  22. data/lib/T4 Templates/SubSonic.TemplatesVB/ActiveRecord/StoredProcedures.tt +30 -0
  23. data/lib/T4 Templates/SubSonic.TemplatesVB/ActiveRecord/StoredProcedures.vb +55 -0
  24. data/lib/T4 Templates/SubSonic.TemplatesVB/ActiveRecord/Structs.tt +57 -0
  25. data/lib/T4 Templates/SubSonic.TemplatesVB/ActiveRecord/Structs.vb +1478 -0
  26. data/lib/T4 Templates/SubSonic.TemplatesVB/ActiveRecord/Tests/FetchTests.vb +52 -0
  27. data/lib/T4 Templates/SubSonic.TemplatesVB/App.config +9 -0
  28. data/lib/T4 Templates/SubSonic.TemplatesVB/My Project/Application.Designer.vb +13 -0
  29. data/lib/T4 Templates/SubSonic.TemplatesVB/My Project/Application.myapp +10 -0
  30. data/lib/T4 Templates/SubSonic.TemplatesVB/My Project/AssemblyInfo.vb +35 -0
  31. data/lib/T4 Templates/SubSonic.TemplatesVB/My Project/Resources.Designer.vb +63 -0
  32. data/lib/T4 Templates/SubSonic.TemplatesVB/My Project/Resources.resx +117 -0
  33. data/lib/T4 Templates/SubSonic.TemplatesVB/My Project/Settings.Designer.vb +73 -0
  34. data/lib/T4 Templates/SubSonic.TemplatesVB/My Project/Settings.settings +7 -0
  35. data/lib/T4 Templates/SubSonic.TemplatesVB/SubSonic.TemplatesVB.vbproj +171 -0
  36. data/lib/T4 Templates/SubSonic.TemplatesVB/SubSonic.TemplatesVB.vbproj.user +5 -0
  37. data/lib/T4 Templates/TemplateProviders/MySQL.ttinclude +278 -0
  38. data/lib/T4 Templates/TemplateProviders/MySQL.ttinclude.orig +303 -0
  39. data/lib/T4 Templates/TemplateProviders/MySQLTest.tt +27 -0
  40. data/lib/T4 Templates/TemplateProviders/SQLite.ttinclude +194 -0
  41. data/lib/T4 Templates/TemplateProviders/SQLite.ttinclude.orig +236 -0
  42. data/lib/T4 Templates/TemplateProviders/SQLiteTest.tt +27 -0
  43. data/lib/T4 Templates/TemplateProviders/Settings.ttinclude +551 -0
  44. metadata +112 -0
@@ -0,0 +1,552 @@
1
+ <#@ template language="C#v3.5" debug="True" hostspecific="True" #>
2
+ <#@ assembly name="EnvDTE" #>
3
+ <#@ assembly name="System.Core.dll" #>
4
+ <#@ assembly name="System.Data" #>
5
+ <#@ assembly name="System.Xml" #>
6
+ <#@ assembly name="System.Configuration" #>
7
+ <#@ import namespace="System.Collections.Generic" #>
8
+ <#@ import namespace="System.Data" #>
9
+ <#@ import namespace="System.Data.SqlClient" #>
10
+ <#@ import namespace="System.Data.Common" #>
11
+ <#@ import namespace="System.Diagnostics" #>
12
+ <#@ import namespace="System.Globalization" #>
13
+ <#@ import namespace="System.IO" #>
14
+ <#@ import namespace="System.Linq" #>
15
+ <#@ import namespace="System.Text" #>
16
+ <#@ import namespace="System.Text.RegularExpressions" #>
17
+ <#@ import namespace="System.Configuration" #>
18
+
19
+ <#+
20
+
21
+ const string Namespace = "Northwind.Data";
22
+ const string ConnectionStringName = "Northwind";
23
+
24
+ //This is the name of your database and is used in naming
25
+ //the repository. By default we set it to the connection string name
26
+ const string DatabaseName = "Northwind";
27
+
28
+ const bool TreatTinyint1AsBool = false;
29
+
30
+ //this is a list of tables you don't want generated
31
+ string[] ExcludeTables = new string[]{
32
+ "sysdiagrams",
33
+ "BuildVersion",
34
+ };
35
+
36
+ string CleanUp(string tableName){
37
+ string result=tableName;
38
+
39
+ //strip blanks
40
+ result=result.Replace(" ","");
41
+
42
+ //put your logic here...
43
+
44
+ return result;
45
+ }
46
+
47
+ string CheckNullable(Column col){
48
+ string result="";
49
+ if(col.IsNullable && col.SysType !="byte[]" && col.SysType !="string")
50
+ result="?";
51
+ return result;
52
+ }
53
+ string GetConnectionString(string connectionStringName){
54
+ var _CurrentProject = GetCurrentProject();
55
+
56
+ string result="";
57
+ ExeConfigurationFileMap configFile = new ExeConfigurationFileMap();
58
+ configFile.ExeConfigFilename = GetConfigPath();
59
+
60
+ if (string.IsNullOrEmpty(configFile.ExeConfigFilename))
61
+ throw new ArgumentNullException("The project does not contain App.config or Web.config file.");
62
+
63
+
64
+ var config = System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(configFile, ConfigurationUserLevel.None);
65
+ var connSection=config.ConnectionStrings;
66
+
67
+ //if the connectionString is empty - which is the defauls
68
+ //look for count-1 - this is the last connection string
69
+ //and takes into account AppServices and LocalSqlServer
70
+ if(string.IsNullOrEmpty(connectionStringName)){
71
+ if(connSection.ConnectionStrings.Count>1){
72
+ result=connSection.ConnectionStrings[connSection.ConnectionStrings.Count-1].ConnectionString;
73
+ }
74
+ }else{
75
+ try{
76
+ result=connSection.ConnectionStrings[connectionStringName].ConnectionString;
77
+ }catch{
78
+ result="There is no connection string name called '"+connectionStringName+"'";
79
+ }
80
+ }
81
+
82
+ return result;
83
+ }
84
+
85
+ string _connectionString="";
86
+ public string ConnectionString{
87
+ get {
88
+ if(String.IsNullOrEmpty(_connectionString)){
89
+
90
+ _connectionString=GetConnectionString(ConnectionStringName);
91
+
92
+ }
93
+
94
+ if(_connectionString.Contains("|DataDirectory|")){
95
+ //have to replace it
96
+ string dataFilePath=GetDataDirectory();
97
+ _connectionString=_connectionString.Replace("|DataDirectory|",dataFilePath);
98
+ }
99
+
100
+ return _connectionString;
101
+ }
102
+ }
103
+
104
+ public EnvDTE.Project GetCurrentProject() {
105
+
106
+ IServiceProvider _ServiceProvider = (IServiceProvider)Host;
107
+ if (_ServiceProvider == null)
108
+ throw new Exception("Host property returned unexpected value (null)");
109
+
110
+ EnvDTE.DTE dte = (EnvDTE.DTE)_ServiceProvider.GetService(typeof(EnvDTE.DTE));
111
+ if (dte == null)
112
+ throw new Exception("Unable to retrieve EnvDTE.DTE");
113
+
114
+ Array activeSolutionProjects = (Array)dte.ActiveSolutionProjects;
115
+ if (activeSolutionProjects == null)
116
+ throw new Exception("DTE.ActiveSolutionProjects returned null");
117
+
118
+ EnvDTE.Project dteProject = (EnvDTE.Project)activeSolutionProjects.GetValue(0);
119
+ if (dteProject == null)
120
+ throw new Exception("DTE.ActiveSolutionProjects[0] returned null");
121
+
122
+ return dteProject;
123
+
124
+ }
125
+
126
+ private string GetProjectPath()
127
+ {
128
+ EnvDTE.Project project = GetCurrentProject();
129
+ System.IO.FileInfo info = new System.IO.FileInfo(project.FullName);
130
+ return info.Directory.FullName;
131
+ }
132
+
133
+ private string GetConfigPath()
134
+ {
135
+ EnvDTE.Project project = GetCurrentProject();
136
+ foreach (EnvDTE.ProjectItem item in project.ProjectItems)
137
+ {
138
+ // if it is the app.config file, then open it up
139
+ if (item.Name.Equals("App.config",StringComparison.InvariantCultureIgnoreCase) || item.Name.Equals("Web.config",StringComparison.InvariantCultureIgnoreCase))
140
+ return GetProjectPath() + "\\" + item.Name;
141
+ }
142
+ return String.Empty;
143
+ }
144
+
145
+ public string GetDataDirectory(){
146
+ EnvDTE.Project project=GetCurrentProject();
147
+ return System.IO.Path.GetDirectoryName(project.FileName)+"\\App_Data\\";
148
+ }
149
+
150
+ public class Table{
151
+
152
+ public List<Column> Columns;
153
+ public List<FKTable> FKTables;
154
+ public string Name;
155
+ public string CleanName;
156
+ public string ClassName;
157
+ public string PrimaryKey;
158
+ public string Schema;
159
+ public string QueryableName;
160
+
161
+ public bool HasLogicalDelete(){
162
+ return this.Columns.Any(x=>x.Name.ToLower()=="deleted" || x.Name.ToLower()=="isdeleted");
163
+ }
164
+ public Column DeleteColumn{
165
+ get{
166
+ Column result=null;
167
+ if(this.Columns.Any(x=>x.Name.ToLower()=="deleted"))
168
+ result=this.Columns.Single(x=>x.Name.ToLower()=="deleted");
169
+ if(this.Columns.Any(x=>x.Name.ToLower()=="isdeleted"))
170
+ result=this.Columns.Single(x=>x.Name.ToLower()=="isdeleted");
171
+ return result;
172
+ }
173
+ }
174
+ public Column PK{
175
+ get{
176
+ return this.Columns.FirstOrDefault(x=>x.IsPK) ?? this.Columns[0];
177
+ }
178
+ }
179
+ public Column Descriptor{
180
+ get{
181
+ if(this.Columns.Count==1){
182
+ return this.Columns[0];
183
+ }else{
184
+ //get the first string column
185
+ Column result=null;
186
+ result=this.Columns.FirstOrDefault(x=>x.SysType.ToLower().Trim()=="string");
187
+ if(result==null)
188
+ result=this.Columns[1];
189
+ return result;
190
+ }
191
+ }
192
+ }
193
+ }
194
+
195
+ public class Column{
196
+ public string Name;
197
+ public string CleanName;
198
+ public string SysType;
199
+ public string DataType;
200
+ public DbType DbType;
201
+ public bool AutoIncrement;
202
+ public bool IsPK;
203
+ public int MaxLength;
204
+ public bool IsNullable;
205
+ public bool IsForeignKey;
206
+ public bool IsUnsigned;
207
+ }
208
+ public class FKTable{
209
+ public string ThisTable;
210
+ public string ThisColumn;
211
+ public string OtherTable;
212
+ public string OtherColumn;
213
+ public string OtherClass;
214
+ public string OtherQueryable;
215
+ }
216
+
217
+ public class SP{
218
+ public string Name;
219
+ public string CleanName;
220
+ public string ClassName;
221
+ public List<SPParam> Parameters;
222
+ public SP(){
223
+ Parameters=new List<SPParam>();
224
+ }
225
+ public string ArgList{
226
+ get{
227
+ StringBuilder sb=new StringBuilder();
228
+ int loopCount=1;
229
+ foreach(var par in Parameters){
230
+ sb.AppendFormat("{0} {1}", par.SysType,par.CleanName);
231
+ if(loopCount<Parameters.Count)
232
+ sb.Append(",");
233
+ loopCount++;
234
+ }
235
+ return sb.ToString();
236
+ }
237
+ }
238
+ }
239
+ public class SPParam{
240
+ public string Name;
241
+ public string CleanName;
242
+ public string SysType;
243
+ public string DbType;
244
+ }
245
+
246
+
247
+ /*
248
+ * SubSonic - http://subsonicproject.com
249
+ *
250
+ * The contents of this file are subject to the New BSD
251
+ * License (the "License"); you may not use this file
252
+ * except in compliance with the License. You may obtain a copy of
253
+ * the License at http://www.opensource.org/licenses/bsd-license.php
254
+ *
255
+ * Software distributed under the License is distributed on an
256
+ * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
257
+ * implied. See the License for the specific language governing
258
+ * rights and limitations under the License.
259
+ */
260
+
261
+ /// <summary>
262
+ /// Summary for the Inflector class
263
+ /// </summary>
264
+ public static class Inflector {
265
+ private static readonly List<InflectorRule> _plurals = new List<InflectorRule>();
266
+ private static readonly List<InflectorRule> _singulars = new List<InflectorRule>();
267
+ private static readonly List<string> _uncountables = new List<string>();
268
+
269
+ /// <summary>
270
+ /// Initializes the <see cref="Inflector"/> class.
271
+ /// </summary>
272
+ static Inflector() {
273
+ AddPluralRule("$", "s");
274
+ AddPluralRule("s$", "s");
275
+ AddPluralRule("(ax|test)is$", "$1es");
276
+ AddPluralRule("(octop|vir)us$", "$1i");
277
+ AddPluralRule("(alias|status)$", "$1es");
278
+ AddPluralRule("(bu)s$", "$1ses");
279
+ AddPluralRule("(buffal|tomat)o$", "$1oes");
280
+ AddPluralRule("([ti])um$", "$1a");
281
+ AddPluralRule("sis$", "ses");
282
+ AddPluralRule("(?:([^f])fe|([lr])f)$", "$1$2ves");
283
+ AddPluralRule("(hive)$", "$1s");
284
+ AddPluralRule("([^aeiouy]|qu)y$", "$1ies");
285
+ AddPluralRule("(x|ch|ss|sh)$", "$1es");
286
+ AddPluralRule("(matr|vert|ind)ix|ex$", "$1ices");
287
+ AddPluralRule("([m|l])ouse$", "$1ice");
288
+ AddPluralRule("^(ox)$", "$1en");
289
+ AddPluralRule("(quiz)$", "$1zes");
290
+
291
+ AddSingularRule("s$", String.Empty);
292
+ AddSingularRule("ss$", "ss");
293
+ AddSingularRule("(n)ews$", "$1ews");
294
+ AddSingularRule("([ti])a$", "$1um");
295
+ AddSingularRule("((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$", "$1$2sis");
296
+ AddSingularRule("(^analy)ses$", "$1sis");
297
+ AddSingularRule("([^f])ves$", "$1fe");
298
+ AddSingularRule("(hive)s$", "$1");
299
+ AddSingularRule("(tive)s$", "$1");
300
+ AddSingularRule("([lr])ves$", "$1f");
301
+ AddSingularRule("([^aeiouy]|qu)ies$", "$1y");
302
+ AddSingularRule("(s)eries$", "$1eries");
303
+ AddSingularRule("(m)ovies$", "$1ovie");
304
+ AddSingularRule("(x|ch|ss|sh)es$", "$1");
305
+ AddSingularRule("([m|l])ice$", "$1ouse");
306
+ AddSingularRule("(bus)es$", "$1");
307
+ AddSingularRule("(o)es$", "$1");
308
+ AddSingularRule("(shoe)s$", "$1");
309
+ AddSingularRule("(cris|ax|test)es$", "$1is");
310
+ AddSingularRule("(octop|vir)i$", "$1us");
311
+ AddSingularRule("(alias|status)$", "$1");
312
+ AddSingularRule("(alias|status)es$", "$1");
313
+ AddSingularRule("^(ox)en", "$1");
314
+ AddSingularRule("(vert|ind)ices$", "$1ex");
315
+ AddSingularRule("(matr)ices$", "$1ix");
316
+ AddSingularRule("(quiz)zes$", "$1");
317
+
318
+ AddIrregularRule("person", "people");
319
+ AddIrregularRule("man", "men");
320
+ AddIrregularRule("child", "children");
321
+ AddIrregularRule("sex", "sexes");
322
+ AddIrregularRule("tax", "taxes");
323
+ AddIrregularRule("move", "moves");
324
+
325
+ AddUnknownCountRule("equipment");
326
+ AddUnknownCountRule("information");
327
+ AddUnknownCountRule("rice");
328
+ AddUnknownCountRule("money");
329
+ AddUnknownCountRule("species");
330
+ AddUnknownCountRule("series");
331
+ AddUnknownCountRule("fish");
332
+ AddUnknownCountRule("sheep");
333
+ }
334
+
335
+ /// <summary>
336
+ /// Adds the irregular rule.
337
+ /// </summary>
338
+ /// <param name="singular">The singular.</param>
339
+ /// <param name="plural">The plural.</param>
340
+ private static void AddIrregularRule(string singular, string plural) {
341
+ AddPluralRule(String.Concat("(", singular[0], ")", singular.Substring(1), "$"), String.Concat("$1", plural.Substring(1)));
342
+ AddSingularRule(String.Concat("(", plural[0], ")", plural.Substring(1), "$"), String.Concat("$1", singular.Substring(1)));
343
+ }
344
+
345
+ /// <summary>
346
+ /// Adds the unknown count rule.
347
+ /// </summary>
348
+ /// <param name="word">The word.</param>
349
+ private static void AddUnknownCountRule(string word) {
350
+ _uncountables.Add(word.ToLower());
351
+ }
352
+
353
+ /// <summary>
354
+ /// Adds the plural rule.
355
+ /// </summary>
356
+ /// <param name="rule">The rule.</param>
357
+ /// <param name="replacement">The replacement.</param>
358
+ private static void AddPluralRule(string rule, string replacement) {
359
+ _plurals.Add(new InflectorRule(rule, replacement));
360
+ }
361
+
362
+ /// <summary>
363
+ /// Adds the singular rule.
364
+ /// </summary>
365
+ /// <param name="rule">The rule.</param>
366
+ /// <param name="replacement">The replacement.</param>
367
+ private static void AddSingularRule(string rule, string replacement) {
368
+ _singulars.Add(new InflectorRule(rule, replacement));
369
+ }
370
+
371
+ /// <summary>
372
+ /// Makes the plural.
373
+ /// </summary>
374
+ /// <param name="word">The word.</param>
375
+ /// <returns></returns>
376
+ public static string MakePlural(string word) {
377
+ return ApplyRules(_plurals, word);
378
+ }
379
+
380
+ /// <summary>
381
+ /// Makes the singular.
382
+ /// </summary>
383
+ /// <param name="word">The word.</param>
384
+ /// <returns></returns>
385
+ public static string MakeSingular(string word) {
386
+ return ApplyRules(_singulars, word);
387
+ }
388
+
389
+ /// <summary>
390
+ /// Applies the rules.
391
+ /// </summary>
392
+ /// <param name="rules">The rules.</param>
393
+ /// <param name="word">The word.</param>
394
+ /// <returns></returns>
395
+ private static string ApplyRules(IList<InflectorRule> rules, string word) {
396
+ string result = word;
397
+ if (!_uncountables.Contains(word.ToLower())) {
398
+ for (int i = rules.Count - 1; i >= 0; i--) {
399
+ string currentPass = rules[i].Apply(word);
400
+ if (currentPass != null) {
401
+ result = currentPass;
402
+ break;
403
+ }
404
+ }
405
+ }
406
+ return result;
407
+ }
408
+
409
+ /// <summary>
410
+ /// Converts the string to title case.
411
+ /// </summary>
412
+ /// <param name="word">The word.</param>
413
+ /// <returns></returns>
414
+ public static string ToTitleCase(string word) {
415
+ return Regex.Replace(ToHumanCase(AddUnderscores(word)), @"\b([a-z])",
416
+ delegate(Match match) { return match.Captures[0].Value.ToUpper(); });
417
+ }
418
+
419
+ /// <summary>
420
+ /// Converts the string to human case.
421
+ /// </summary>
422
+ /// <param name="lowercaseAndUnderscoredWord">The lowercase and underscored word.</param>
423
+ /// <returns></returns>
424
+ public static string ToHumanCase(string lowercaseAndUnderscoredWord) {
425
+ return MakeInitialCaps(Regex.Replace(lowercaseAndUnderscoredWord, @"_", " "));
426
+ }
427
+
428
+
429
+ /// <summary>
430
+ /// Adds the underscores.
431
+ /// </summary>
432
+ /// <param name="pascalCasedWord">The pascal cased word.</param>
433
+ /// <returns></returns>
434
+ public static string AddUnderscores(string pascalCasedWord) {
435
+ return Regex.Replace(Regex.Replace(Regex.Replace(pascalCasedWord, @"([A-Z]+)([A-Z][a-z])", "$1_$2"), @"([a-z\d])([A-Z])", "$1_$2"), @"[-\s]", "_").ToLower();
436
+ }
437
+
438
+ /// <summary>
439
+ /// Makes the initial caps.
440
+ /// </summary>
441
+ /// <param name="word">The word.</param>
442
+ /// <returns></returns>
443
+ public static string MakeInitialCaps(string word) {
444
+ return String.Concat(word.Substring(0, 1).ToUpper(), word.Substring(1).ToLower());
445
+ }
446
+
447
+ /// <summary>
448
+ /// Makes the initial lower case.
449
+ /// </summary>
450
+ /// <param name="word">The word.</param>
451
+ /// <returns></returns>
452
+ public static string MakeInitialLowerCase(string word) {
453
+ return String.Concat(word.Substring(0, 1).ToLower(), word.Substring(1));
454
+ }
455
+
456
+
457
+ /// <summary>
458
+ /// Determine whether the passed string is numeric, by attempting to parse it to a double
459
+ /// </summary>
460
+ /// <param name="str">The string to evaluated for numeric conversion</param>
461
+ /// <returns>
462
+ /// <c>true</c> if the string can be converted to a number; otherwise, <c>false</c>.
463
+ /// </returns>
464
+ public static bool IsStringNumeric(string str) {
465
+ double result;
466
+ return (double.TryParse(str, NumberStyles.Float, NumberFormatInfo.CurrentInfo, out result));
467
+ }
468
+
469
+ /// <summary>
470
+ /// Adds the ordinal suffix.
471
+ /// </summary>
472
+ /// <param name="number">The number.</param>
473
+ /// <returns></returns>
474
+ public static string AddOrdinalSuffix(string number) {
475
+ if (IsStringNumeric(number)) {
476
+ int n = int.Parse(number);
477
+ int nMod100 = n % 100;
478
+
479
+ if (nMod100 >= 11 && nMod100 <= 13)
480
+ return String.Concat(number, "th");
481
+
482
+ switch (n % 10) {
483
+ case 1:
484
+ return String.Concat(number, "st");
485
+ case 2:
486
+ return String.Concat(number, "nd");
487
+ case 3:
488
+ return String.Concat(number, "rd");
489
+ default:
490
+ return String.Concat(number, "th");
491
+ }
492
+ }
493
+ return number;
494
+ }
495
+
496
+ /// <summary>
497
+ /// Converts the underscores to dashes.
498
+ /// </summary>
499
+ /// <param name="underscoredWord">The underscored word.</param>
500
+ /// <returns></returns>
501
+ public static string ConvertUnderscoresToDashes(string underscoredWord) {
502
+ return underscoredWord.Replace('_', '-');
503
+ }
504
+
505
+
506
+ #region Nested type: InflectorRule
507
+
508
+ /// <summary>
509
+ /// Summary for the InflectorRule class
510
+ /// </summary>
511
+ private class InflectorRule {
512
+ /// <summary>
513
+ ///
514
+ /// </summary>
515
+ public readonly Regex regex;
516
+
517
+ /// <summary>
518
+ ///
519
+ /// </summary>
520
+ public readonly string replacement;
521
+
522
+ /// <summary>
523
+ /// Initializes a new instance of the <see cref="InflectorRule"/> class.
524
+ /// </summary>
525
+ /// <param name="regexPattern">The regex pattern.</param>
526
+ /// <param name="replacementText">The replacement text.</param>
527
+ public InflectorRule(string regexPattern, string replacementText) {
528
+ regex = new Regex(regexPattern, RegexOptions.IgnoreCase);
529
+ replacement = replacementText;
530
+ }
531
+
532
+ /// <summary>
533
+ /// Applies the specified word.
534
+ /// </summary>
535
+ /// <param name="word">The word.</param>
536
+ /// <returns></returns>
537
+ public string Apply(string word) {
538
+ if (!regex.IsMatch(word))
539
+ return null;
540
+
541
+ string replace = regex.Replace(word, replacement);
542
+ if (word == word.ToUpper())
543
+ replace = replace.ToUpper();
544
+
545
+ return replace;
546
+ }
547
+ }
548
+
549
+ #endregion
550
+ }
551
+
552
+ #>