-
Notifications
You must be signed in to change notification settings - Fork 0
/
feed.xml
1164 lines (969 loc) · 132 KB
/
feed.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
<title>Jakub Malczak Developer Abroad</title>
<generator uri="https://github.com/mojombo/jekyll">Jekyll</generator>
<link rel="self" type="application/atom+xml" href="http://malczak.net/feed.xml" />
<link rel="alternate" type="text/html" href="http://malczak.net/" />
<updated>2016-04-05T23:52:49+02:00</updated>
<id>http://malczak.net/</id>
<author>
<name>Jakub Malczak</name>
<uri>http://malczak.net/</uri>
<email>jmalczak@gmail.com</email>
</author>
<entry>
<title type="html"><![CDATA[Setting ASP.NET application auto start from powershell.]]></title>
<link rel="alternate" type="text/html" href="http://malczak.net/2015/11/03/setting-asp-net-autostart-from-powershell.html"/>
<id>http://malczak.net/2015/11/03/setting-asp-net-autostart-from-powershell</id>
<published>2015-11-03T00:00:00+01:00</published>
<updated>2015-11-03T00:00:00+01:00</updated>
<author>
<name>Jakub Malczak</name>
<uri>http://malczak.net</uri>
<email>jmalczak@gmail.com</email>
</author>
<content type="html">
<h3>Why it takes so long</h3>
<p>We all know the feeling when we load our ASP.NET app for the first time, and it takes much longer
to execute than the following requests. That is caused by all the things we put to Application_Start
in Global.asax. We all know that this method will be called when first request hits our application,
so we use it as a good place to initialize our app. This makes it much slower to access for the first
time. </p>
<h3>One way of solving the problem</h3>
<p>Many people were trying to solve the problem by themselves by scheduling calls to website to invoke
this first request and warm up application. This wasn&#39;t the most elegant solution since you have to
take under the consideration your application pool recycle time, also when your app pool crash IIS
it may not be wormed up because your scheduler doesn&#39;t know about it. </p>
<h3>There is a better way in ASP.NET 4</h3>
<p>Microsoft team included auto start feature in ASP.NET 4. You can read more about it in this article by
Scott Guthrie <a href="http://weblogs.asp.net/scottgu/auto-start-asp-net-applications-vs-2010-and-net-4-0-series">Auto-Start ASP.NET Applications (VS 2010 and .NET 4.0 Series)</a>. You just
need to configure your IIS in specific way and add implementation of IProcessHostPreloadClient interface
which will contain your warm up code. </p>
<h3>What if you are lazy and you want to use PowerShell to configure your website to auto start</h3>
<p>You still need to implement IProcessHostPreloadClient in your application. Then can use following
PowerShell code to configure your website. First you need to change your app pool start mode to
AlwaysRunning.</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><code class="language-powershell" data-lang="powershell">1
2
3
4
5
6</code></pre></div></td><td class="code"><div class="highlight"><pre><span class="c"># This adds IIS manipulation snap in</span>
<span class="nb">Add-PSSnapin</span> <span class="n">WebAdministration</span> <span class="n">-ErrorAction</span> <span class="n">SilentlyContinue</span>
<span class="nb">Import-Module</span> <span class="n">WebAdministration</span> <span class="n">-ErrorAction</span> <span class="n">SilentlyContinue</span>
<span class="c"># Setting application pool AlwaysRunning where $appPoolName is name of our app pool</span>
<span class="nb">Set-ItemProperty</span> <span class="s2">&quot;IIS:\AppPools\$appPoolName&quot;</span> <span class="n">-Name</span> <span class="n">startMode</span> <span class="n">-Value</span> <span class="n">AlwaysRunning</span>
</pre></div>
</td></tr></table>
<p>Now our app pool will be always running, but this won&#39;t change much in case of our first request
start up time. We have to make sure that after app pool start our warm up code will be invoked. So
we have to add auto start provider as it&#39;s explained in Scott article:</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><code class="language-powershell" data-lang="powershell">1
2
3</code></pre></div></td><td class="code"><div class="highlight"><pre><span class="c"># Adding new auto start provider where $serviceName is unique name of our provider and $serviceType</span>
<span class="c"># is type that implements our provider</span>
<span class="nb">Add-WebConfiguration</span> <span class="n">-filter</span> <span class="p">/</span><span class="n">system</span><span class="p">.</span><span class="n">applicationHost</span><span class="p">/</span><span class="n">serviceAutoStartProviders</span> <span class="n">-Value</span> <span class="p">@{</span><span class="n">name</span><span class="p">=</span><span class="nv">$serviceName</span><span class="p">;</span> <span class="n">type</span><span class="p">=</span><span class="nv">$serviceType</span><span class="p">}</span>
</pre></div>
</td></tr></table>
<p>At the end we have to tell our web application to use configured auto start provider.</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><code class="language-powershell" data-lang="powershell">1
2
3
4
5</code></pre></div></td><td class="code"><div class="highlight"><pre><span class="c"># Set web site auto start enabled where $webSiteName is our web site name</span>
<span class="nb">Set-ItemProperty</span> <span class="s2">&quot;IIS:\Sites\$webSiteName&quot;</span> <span class="n">-Name</span> <span class="n">applicationDefaults</span><span class="p">.</span><span class="n">serviceAutoStartEnabled</span> <span class="n">-Value</span> <span class="n">True</span>
<span class="c"># Set web site auto start provider where $webSiteName is our web site name and $serviceName is name configured</span>
<span class="c"># in previous step</span>
<span class="nb">Set-ItemProperty</span> <span class="s2">&quot;IIS:\Sites\$webSiteName&quot;</span> <span class="n">-Name</span> <span class="n">applicationDefaults</span><span class="p">.</span><span class="n">serviceAutoStartEnabled</span> <span class="n">-Value</span> <span class="nv">$serviceName</span>
</pre></div>
</td></tr></table>
<p>Now you can go to your IIS Manager and confirm that all settings have been applied correctly. Now
when your app pool will be recycled, code you put in implementation of IProcessHostPreloadClient will
be executed to warm up your application.</p>
<h3>What if I use Octopus Deployment</h3>
<p>If you use Octopus Deployment (and you should, since it&#39;s great piece of software) you can import
Octopus Library tasks to your Octopus Deployment installation. To do that, visit <a href="https://github.com/OctopusDeploy/Library/tree/master/step-templates">Octopus Library</a> and download following templates:</p>
<ul>
<li>iis-apppool-update-property.json</li>
<li>iis-website-update-property.json</li>
<li>iis-autostartprovider-add.json</li>
</ul>
<p>After importing them you can set web site, app pool and auto start provider settings directly from your
deployment server.</p>
<p><a href="http://malczak.net/2015/11/03/setting-asp-net-autostart-from-powershell.html">Setting ASP.NET application auto start from powershell.</a> was originally published by Jakub Malczak at <a href="http://malczak.net">Jakub Malczak Developer Abroad</a> on November 03, 2015.</p></content>
</entry>
<entry>
<title type="html"><![CDATA[Poor man's C# grunt-init.]]></title>
<link rel="alternate" type="text/html" href="http://malczak.net/programming/c%23/2015/10/18/poor-mans-csharp-grunt-init/"/>
<id>http://malczak.net/programming/c%23/2015/10/18/poor-mans-csharp-grunt-init</id>
<published>2015-10-18T00:00:00+02:00</published>
<updated>2015-10-18T00:00:00+02:00</updated>
<author>
<name>Jakub Malczak</name>
<uri>http://malczak.net</uri>
<email>jmalczak@gmail.com</email>
</author>
<content type="html">
<h3>Project Bootstrap Idea</h3>
<p>Unfortunately, I couldn&#39;t be on DevDay 2015 conference. But I was watching all videos recommended by
other developers. One of the talks I really liked was &quot;From Homogeneous Monolith to Radically
Heterogeneous Microservices Architecture&quot; by Chad Fowler. If you haven&#39;t seen it, you can find
youtube video below.
<div class="embed-responsive embed-responsive-16by9 margin-small">
<iframe src="https://www.youtube.com/embed/v17DMiFHnB8"
allowfullscreen></iframe>
</div>
Chad is talking about move from monolith to microservices architecture they did in Wunderlist. When
defining microservices they put constraint on service size. In Wunderlist size of newly created
service should fit on one screen. This is quite radical, but it works for them based on the Chad&#39;s
talk. To be able to bootstrap services quickly they have created microservice template so creating
new service is as easy as clonning it from template and adding some business logic. So I thought
that this is quite useful.</p>
<h3>Microservices in my current project</h3>
<p>I use microservices in my current project as well. We don&#39;t have any specific constraint on service
size. We just try to be pragmatic and when it grows too large we extract smaller services. Anyway
we end up creating services very often. And since we mostly use the same set of components to build
service we waste a lot of time on task which may be automated in the same way Chad did it.</p>
<h3>Grunt-init approach</h3>
<p>There is already a tool for that, that use node.js. It&#39;s called <a href="http://gruntjs.com/project-scaffolding">grunt-init</a>.
and you can use it to bootstrap different kinds of projects. This is an example how you use it to
bootstrap C# project: <a href="https://github.com/nosami/grunt-init-csharpsolution">grunt-init-csharpsolution</a>.
Grunt-init just ask you for values needed to bootstrap project and then rename files and replace
values in solution directory. That&#39;s easy. But due to the variable replacement format </p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><code class="language-xml" data-lang="xml">1</code></pre></div></td><td class="code"><div class="highlight"><pre>{%= nametoreplace %}
</pre></div>
</td></tr></table>
<p>you cannot open template solution in Visual Studio since replacement value contains some illegal
C# characters. And I have found really convenient to be able to edit template in Visual Studio so yoou
don&#39;t have to mess with csproj, sln files.</p>
<h3>Poor man&#39;s powershell grunt-init replacement</h3>
<p>To be able to open template in Visual Studio. I have used PROJECT_NAME as a variable replacement key
and in connection with simple PowerShell script you can do the same thing. Below you can see how it
works in practice.
<img class="img-responsive center-block padding-small"
src="http://developerabroad.com/img/poormansgruntinit/powershell-init-csharp-web.gif"
alt="Poor man's powershell grunt-init" />
You can check out example source code on <a href="https://github.com/jmalczak/powershell-init-csharp-web">here</a>
on github. Feel free to fork and and make your own changes. </p>
<p><a href="http://malczak.net/programming/c%23/2015/10/18/poor-mans-csharp-grunt-init/">Poor man's C# grunt-init.</a> was originally published by Jakub Malczak at <a href="http://malczak.net">Jakub Malczak Developer Abroad</a> on October 18, 2015.</p></content>
</entry>
<entry>
<title type="html"><![CDATA[Use .NET resources from JavaScript.]]></title>
<link rel="alternate" type="text/html" href="http://malczak.net/programming/t4/resources/localization/2015/01/11/dot-net-resources-from-javascript/"/>
<id>http://malczak.net/programming/t4/resources/localization/2015/01/11/dot-net-resources-from-javascript</id>
<published>2015-01-11T00:00:00+01:00</published>
<updated>2015-01-11T00:00:00+01:00</updated>
<author>
<name>Jakub Malczak</name>
<uri>http://malczak.net</uri>
<email>jmalczak@gmail.com</email>
</author>
<content type="html">
<h3>Problem</h3>
<p>It is often the case, that you would like to use the same set of resources from both, server side and client side code. There is a couple of solutions to this problem, which I am going to describe briefly.</p>
<h3>HTTP handler or lightweight service</h3>
<p>You can find an example of HTTP handler implementation on Rick Strahl <a href="http://weblog.west-wind.com/posts/2009/Apr/02/A-Localization-Handler-to-serve-ASPNET-Resources-to-JavaScript">web page</a>. It is a simple HTTP handler which returns JavaScript object for either local or global resource set. In order to use it you should add JavaScript script tag with src set to URL of your HTTP handler. Culture is provided via query string and included in the original script URL. Example code:</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><code class="language-c#" data-lang="c#">1
2
3
4</code></pre></div></td><td class="code"><div class="highlight"><pre><span class="p">&lt;</span><span class="n">script</span> <span class="n">src</span><span class="p">=</span><span class="err">&#39;</span><span class="s">&quot; + </span>
<span class="n">Westwind</span><span class="p">.</span><span class="n">Globalization</span><span class="p">.</span><span class="n">JavaScriptResourceHandler</span><span class="p">.</span><span class="n">GetJavaScriptGlobalResourcesUrl</span><span class="p">(</span><span class="s">&quot;globalRes&quot;</span><span class="p">,</span><span class="s">&quot;Resources&quot;</span><span class="p">)</span> <span class="p">+</span>
<span class="s">&quot;&#39; type=&#39;text/javascript&#39;&gt;</span>
<span class="p">&lt;/</span><span class="n">script</span><span class="p">&gt;</span><span class="s">&quot;</span>
</pre></div>
</td></tr></table>
<p>And this can embeed following JavaScript in your page:</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><code class="language-javascript" data-lang="javascript">1
2
3
4</code></pre></div></td><td class="code"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">globalRes</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">Today</span><span class="o">:</span> <span class="s1">&#39;Heute&#39;</span><span class="p">,</span>
<span class="nx">Yesterday</span><span class="o">:</span> <span class="s1">&#39;Gestern&#39;</span>
<span class="p">};</span>
</pre></div>
</td></tr></table>
<p>Lately when Microservices are becoming more and more popular, the same, may be achieved by returning your JavaScript form simple WebApi REST service. This solution will do the work, but it&#39;s not the best one you can use. First of all, you can&#39;t minimize JavaScript code. You would have to do it on the fly. You also loose intellisense for all of you resources, when you develop JavaScript code. This may sound like a minor issue, but when you have hundreds of resources, it&#39;s not helping. One huge advantage of this approach is that you can change your localization texts in runtime, and returned JavaScript will be regenerated again and will reflect your changes.</p>
<h3>Inline localization embedding</h3>
<p>This is the easiest method. In your view engine files (.aspx or .cshtml), you can create explicit resource object, and select only those resources which are really needed in JavaScript code. For example, you can create localization object like this:</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><code class="language-javascript" data-lang="javascript">1
2
3
4</code></pre></div></td><td class="code"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">localization</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">Today</span><span class="o">:</span> <span class="s1">&#39;@Resources.YourResourceClass.Today&#39;</span><span class="p">,</span>
<span class="nx">Yesterday</span><span class="o">:</span> <span class="s1">&#39;@Resources.YourResourceClass.Yesterday&#39;</span>
<span class="p">};</span>
</pre></div>
</td></tr></table>
<p>This will make sure that your localization object will be rendered correctly in a current culture. Simple and powerful solution, but not without it&#39;s own drawbacks. You still can&#39;t minify this code. It&#39;s also required to put this code in view engine files, since .js files are not processed by ASP.NET pipeline, you can&#39;t place code like that where it belongs to. So you can imagine the long listings of those in every view. Depending where you use your localization object, you may have some intellisense support. This solution is also a perfect choice if you will change localization texts after deployment.</p>
<h3>JavaScript resource files generated using T4 templates</h3>
<p>Another approach to the problem, may be to generate set of JavaScript files which will hold translated resources in all of available languages. First step would be to create class to get all resources available in our application in the every supported culture. We will use ResourceModel class for this reason:</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><code class="language-csharp" data-lang="csharp"> 1
2
3
4
5
6
7
8
9
10</code></pre></div></td><td class="code"><div class="highlight"><pre><span class="k">public</span> <span class="k">class</span> <span class="nc">ResourceModel</span>
<span class="p">{</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">ResourceFileName</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">CultureCode</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">Key</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">Value</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span>
</pre></div>
</td></tr></table>
<p>To get list of resources, first we need to get all resource files by using GetManifestResourceNames method on assembly to which resources are compiled into. In my case it&#39;s Shared assembly.</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><code class="language-c#" data-lang="c#">1</code></pre></div></td><td class="code"><div class="highlight"><pre><span class="k">typeof</span><span class="p">(</span><span class="n">Shared</span><span class="p">).</span><span class="n">Assembly</span><span class="p">.</span><span class="n">GetManifestResourceNames</span><span class="p">()</span>
</pre></div>
</td></tr></table>
<p>Next we parse resource set name and get all resources for every set. Entire ResourceService class is available below. It will be used within T4 template to generate single JavaScript file per culture.</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><code class="language-c#" data-lang="c#"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55</code></pre></div></td><td class="code"><div class="highlight"><pre><span class="k">public</span> <span class="k">class</span> <span class="nc">ResourceService</span>
<span class="p">{</span>
<span class="k">private</span> <span class="k">const</span> <span class="kt">string</span> <span class="n">FileNameGroup</span> <span class="p">=</span> <span class="s">&quot;fileName&quot;</span><span class="p">;</span>
<span class="k">private</span> <span class="k">const</span> <span class="kt">string</span> <span class="n">ResourceSetGroup</span> <span class="p">=</span> <span class="s">&quot;resourceSet&quot;</span><span class="p">;</span>
<span class="k">private</span> <span class="k">const</span> <span class="kt">string</span> <span class="n">CultureCodeGroup</span> <span class="p">=</span> <span class="s">&quot;cultureCode&quot;</span><span class="p">;</span>
<span class="k">private</span> <span class="k">static</span> <span class="k">readonly</span> <span class="kt">object</span> <span class="n">Lock</span> <span class="p">=</span> <span class="k">new</span> <span class="kt">object</span><span class="p">();</span>
<span class="k">private</span> <span class="k">readonly</span> <span class="kt">string</span> <span class="n">resourceFolder</span><span class="p">;</span>
<span class="k">private</span> <span class="kt">string</span> <span class="n">fileNameRegex</span> <span class="p">=</span> <span class="kt">string</span><span class="p">.</span><span class="n">Format</span><span class="p">(</span><span class="s">&quot;^.*\\.(?&lt;{0}&gt;.*).resources$&quot;</span><span class="p">,</span> <span class="n">FileNameGroup</span><span class="p">);</span>
<span class="k">private</span> <span class="kt">string</span> <span class="n">resourceSetRegex</span> <span class="p">=</span> <span class="kt">string</span><span class="p">.</span><span class="n">Format</span><span class="p">(</span><span class="s">&quot;^(?&lt;{0}&gt;.*).resources$&quot;</span><span class="p">,</span> <span class="n">ResourceSetGroup</span><span class="p">);</span>
<span class="k">private</span> <span class="kt">string</span> <span class="n">cultureCodeRegex</span> <span class="p">=</span> <span class="kt">string</span><span class="p">.</span><span class="n">Format</span><span class="p">(</span><span class="s">&quot;^.*\\.(?&lt;{0}&gt;.2-.2).resx$&quot;</span><span class="p">,</span> <span class="n">CultureCodeGroup</span><span class="p">);</span>
<span class="k">public</span> <span class="nf">ResourceService</span><span class="p">(</span><span class="kt">string</span> <span class="n">resourceFolder</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="n">resourceFolder</span> <span class="p">=</span> <span class="n">resourceFolder</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">public</span> <span class="n">List</span><span class="p">&lt;</span><span class="n">ResourceModel</span><span class="p">&gt;</span> <span class="n">GetResources</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">return</span> <span class="p">(</span><span class="k">from</span> <span class="n">resourceSet</span> <span class="k">in</span> <span class="k">typeof</span><span class="p">(</span><span class="n">Shared</span><span class="p">).</span><span class="n">Assembly</span><span class="p">.</span><span class="n">GetManifestResourceNames</span><span class="p">()</span>
<span class="n">let</span> <span class="n">setName</span> <span class="p">=</span> <span class="n">Regex</span><span class="p">.</span><span class="n">Match</span><span class="p">(</span><span class="n">resourceSet</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="n">resourceSetRegex</span><span class="p">).</span><span class="n">Groups</span><span class="p">[</span><span class="n">ResourceSetGroup</span><span class="p">].</span><span class="n">Value</span>
<span class="n">let</span> <span class="n">resourceManager</span> <span class="p">=</span> <span class="k">new</span> <span class="n">ResourceManager</span><span class="p">(</span><span class="n">setName</span><span class="p">,</span> <span class="k">typeof</span><span class="p">(</span><span class="n">Shared</span><span class="p">).</span><span class="n">Assembly</span><span class="p">)</span>
<span class="k">from</span> <span class="n">culture</span> <span class="k">in</span> <span class="k">this</span><span class="p">.</span><span class="n">GetAvailableCultures</span><span class="p">()</span>
<span class="n">let</span> <span class="n">resource</span> <span class="p">=</span> <span class="n">resourceManager</span><span class="p">.</span><span class="n">GetResourceSet</span><span class="p">(</span><span class="n">culture</span><span class="p">,</span> <span class="k">true</span><span class="p">,</span> <span class="k">true</span><span class="p">)</span>
<span class="n">let</span> <span class="n">fileName</span> <span class="p">=</span> <span class="n">Regex</span><span class="p">.</span><span class="n">Match</span><span class="p">(</span><span class="n">resourceSet</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="n">fileNameRegex</span><span class="p">).</span><span class="n">Groups</span><span class="p">[</span><span class="n">FileNameGroup</span><span class="p">].</span><span class="n">Value</span>
<span class="k">from</span> <span class="n">DictionaryEntry</span> <span class="n">singleResource</span> <span class="k">in</span> <span class="n">resource</span>
<span class="k">select</span>
<span class="k">new</span> <span class="n">ResourceModel</span>
<span class="p">{</span>
<span class="n">ResourceFileName</span> <span class="p">=</span> <span class="n">fileName</span><span class="p">,</span>
<span class="n">Key</span> <span class="p">=</span> <span class="p">(</span><span class="kt">string</span><span class="p">)</span><span class="n">singleResource</span><span class="p">.</span><span class="n">Key</span><span class="p">,</span>
<span class="n">Value</span> <span class="p">=</span> <span class="p">(</span><span class="kt">string</span><span class="p">)</span><span class="n">singleResource</span><span class="p">.</span><span class="n">Value</span><span class="p">,</span>
<span class="n">CultureCode</span> <span class="p">=</span> <span class="n">culture</span><span class="p">.</span><span class="n">Name</span>
<span class="p">}).</span><span class="n">ToList</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">private</span> <span class="n">List</span><span class="p">&lt;</span><span class="n">CultureInfo</span><span class="p">&gt;</span> <span class="n">GetAvailableCultures</span><span class="p">()</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">cultures</span> <span class="p">=</span> <span class="k">new</span> <span class="n">List</span><span class="p">&lt;</span><span class="n">CultureInfo</span><span class="p">&gt;</span> <span class="p">{</span> <span class="n">CultureInfo</span><span class="p">.</span><span class="n">InvariantCulture</span> <span class="p">};</span>
<span class="n">cultures</span><span class="p">.</span><span class="n">AddRange</span><span class="p">(</span>
<span class="k">from</span> <span class="n">file</span> <span class="k">in</span> <span class="n">Directory</span><span class="p">.</span><span class="n">GetFiles</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="n">resourceFolder</span><span class="p">)</span>
<span class="k">select</span> <span class="n">Regex</span><span class="p">.</span><span class="n">Match</span><span class="p">(</span><span class="n">file</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="n">cultureCodeRegex</span><span class="p">)</span>
<span class="k">into</span> <span class="n">match</span>
<span class="k">where</span> <span class="n">match</span><span class="p">.</span><span class="n">Success</span>
<span class="k">select</span> <span class="k">new</span> <span class="nf">CultureInfo</span><span class="p">(</span><span class="n">match</span><span class="p">.</span><span class="n">Groups</span><span class="p">[</span><span class="n">CultureCodeGroup</span><span class="p">].</span><span class="n">Value</span><span class="p">));</span>
<span class="k">return</span> <span class="n">cultures</span><span class="p">.</span><span class="n">Distinct</span><span class="p">().</span><span class="n">ToList</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
</td></tr></table>
<p>To generate multiple JavaScript files from the T4 template, we need to use <a href="https://t4toolbox.codeplex.com/">T4Toolbox</a> Visual Studio extension. You can either download it from <a href="https://visualstudiogallery.msdn.microsoft.com/7f9bd62f-2505-4aa4-9378-ee7830371684">Visual Studio Gallery</a> or using extension manager:</p>
<p><img class="img-responsive center-block" src="http://developerabroad.com/img/t4toolboxInstall.jpg" alt="T4 Toolbox" /></p>
<p>It is possible to do the same without T4Toolbox, but our template would be much bigger, since we would have to not only create many files, but also use Visual Studio automation to add those files to a current project. By using T4Toolbox, it&#39;s no longer a problem, since extension will do the above actions for us. After installation and restart, it&#39;s time to add resource.tt template:</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><code class="language-c#" data-lang="c#"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71</code></pre></div></td><td class="code"><div class="highlight"><pre><span class="p">&lt;</span><span class="err">#@</span> <span class="n">template</span> <span class="n">language</span><span class="p">=</span><span class="s">&quot;C#&quot;</span> <span class="n">debug</span><span class="p">=</span><span class="s">&quot;True&quot;</span> <span class="n">hostspecific</span><span class="p">=</span><span class="s">&quot;True&quot;</span> <span class="err">#</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="err">#@</span> <span class="n">include</span> <span class="n">file</span><span class="p">=</span><span class="s">&quot;T4Toolbox.tt&quot;</span> <span class="err">#</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="err">#@</span> <span class="n">output</span> <span class="n">extension</span><span class="p">=</span><span class="s">&quot;js&quot;</span> <span class="err">#</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="err">#@</span> <span class="n">assembly</span> <span class="n">name</span><span class="p">=</span><span class="s">&quot;System.Core&quot;</span> <span class="err">#</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="err">#@</span> <span class="n">assembly</span> <span class="n">name</span><span class="p">=</span><span class="s">&quot;$(TargetDir)\WebSiteCore.Common.dll&quot;</span> <span class="err">#</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="err">#@</span> <span class="n">assembly</span> <span class="n">name</span><span class="p">=</span><span class="s">&quot;$(TargetDir)\WebSiteCore.BLL.dll&quot;</span> <span class="err">#</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="err">#@</span> <span class="n">import</span> <span class="n">namespace</span><span class="p">=</span><span class="s">&quot;System.Collections.Generic&quot;</span> <span class="err">#</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="err">#@</span> <span class="n">import</span> <span class="n">namespace</span><span class="p">=</span><span class="s">&quot;System.Linq&quot;</span> <span class="err">#</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="err">#@</span> <span class="n">import</span> <span class="n">namespace</span><span class="p">=</span><span class="s">&quot;WebSiteCore.Common.Models.Infrastructure.Resource&quot;</span> <span class="err">#</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="err">#@</span> <span class="n">import</span> <span class="n">namespace</span><span class="p">=</span><span class="s">&quot;WebSiteCore.Common.Infrastructure.Services&quot;</span> <span class="err">#</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="err">#</span>
<span class="kt">var</span> <span class="n">resourceService</span> <span class="p">=</span> <span class="k">new</span> <span class="n">ResourceService</span><span class="p">(</span><span class="n">Host</span><span class="p">.</span><span class="n">ResolvePath</span><span class="p">(</span><span class="s">@&quot;..\..\..\..\..\WebSiteCore.Resources&quot;</span><span class="p">));</span>
<span class="kt">var</span> <span class="n">resources</span> <span class="p">=</span> <span class="n">resourceService</span><span class="p">.</span><span class="n">GetResources</span><span class="p">();</span>
<span class="k">foreach</span> <span class="p">(</span><span class="kt">var</span> <span class="n">resourceInOneCulture</span> <span class="k">in</span> <span class="n">resources</span><span class="p">.</span><span class="n">GroupBy</span><span class="p">(</span><span class="n">r</span> <span class="p">=&gt;</span> <span class="n">r</span><span class="p">.</span><span class="n">CultureCode</span><span class="p">))</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">r</span> <span class="p">=</span> <span class="k">new</span> <span class="n">ResourceTemplate</span><span class="p">(</span><span class="n">resourceInOneCulture</span><span class="p">.</span><span class="n">Key</span><span class="p">,</span> <span class="n">resourceInOneCulture</span><span class="p">.</span><span class="n">ToList</span><span class="p">());</span>
<span class="n">r</span><span class="p">.</span><span class="n">Render</span><span class="p">();</span>
<span class="p">}</span>
<span class="err">#</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="err">#</span><span class="p">+</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">ResourceTemplate</span> <span class="p">:</span> <span class="n">Template</span>
<span class="p">{</span>
<span class="k">private</span> <span class="k">readonly</span> <span class="kt">string</span> <span class="n">cultureName</span><span class="p">;</span>
<span class="k">private</span> <span class="k">readonly</span> <span class="n">List</span><span class="p">&lt;</span><span class="n">ResourceModel</span><span class="p">&gt;</span> <span class="n">resources</span><span class="p">;</span>
<span class="k">public</span> <span class="nf">ResourceTemplate</span><span class="p">(</span><span class="kt">string</span> <span class="n">cultureName</span><span class="p">,</span> <span class="n">List</span><span class="p">&lt;</span><span class="n">ResourceModel</span><span class="p">&gt;</span> <span class="n">resources</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="n">cultureName</span> <span class="p">=</span> <span class="n">cultureName</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="n">resources</span> <span class="p">=</span> <span class="n">resources</span><span class="p">;</span>
<span class="k">if</span><span class="p">(!</span><span class="kt">string</span><span class="p">.</span><span class="n">IsNullOrEmpty</span><span class="p">(</span><span class="n">cultureName</span><span class="p">))</span>
<span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="n">Output</span><span class="p">.</span><span class="n">File</span> <span class="p">=</span> <span class="kt">string</span><span class="p">.</span><span class="n">Format</span><span class="p">(</span><span class="s">&quot;resource.{0}.js&quot;</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="n">cultureName</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">override</span> <span class="kt">string</span> <span class="nf">TransformText</span><span class="p">()</span>
<span class="p">{</span>
<span class="err">#</span><span class="p">&gt;</span>
<span class="n">webSiteCore</span><span class="p">.</span><span class="n">Resource</span> <span class="p">=</span> <span class="p">(</span><span class="n">function</span> <span class="p">(){</span>
<span class="kt">var</span> <span class="n">resources</span> <span class="p">=</span> <span class="p">{</span>
<span class="p">&lt;</span><span class="err">#</span><span class="p">+</span> <span class="k">foreach</span> <span class="p">(</span><span class="kt">var</span> <span class="n">resourceGroup</span> <span class="k">in</span> <span class="k">this</span><span class="p">.</span><span class="n">resources</span><span class="p">.</span><span class="n">GroupBy</span><span class="p">(</span><span class="n">r</span> <span class="p">=&gt;</span> <span class="n">r</span><span class="p">.</span><span class="n">ResourceFileName</span><span class="p">))</span>
<span class="p">{</span>
<span class="n">PopIndent</span><span class="p">();</span>
<span class="n">PushIndent</span><span class="p">(</span><span class="s">&quot; &quot;</span><span class="p">);</span>
<span class="n">WriteLine</span><span class="p">(</span><span class="n">resourceGroup</span><span class="p">.</span><span class="n">Key</span> <span class="p">+</span> <span class="s">&quot;: {&quot;</span><span class="p">)</span> <span class="p">;</span>
<span class="k">foreach</span> <span class="p">(</span><span class="kt">var</span> <span class="n">resource</span> <span class="k">in</span> <span class="n">resourceGroup</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">PushIndent</span><span class="p">(</span><span class="s">&quot; &quot;</span><span class="p">);</span>
<span class="n">WriteLine</span><span class="p">(</span><span class="n">resource</span><span class="p">.</span><span class="n">Key</span> <span class="p">+</span> <span class="s">&quot; : &#39;&quot;</span> <span class="p">+</span> <span class="n">System</span><span class="p">.</span><span class="n">Net</span><span class="p">.</span><span class="n">WebUtility</span><span class="p">.</span><span class="n">HtmlEncode</span><span class="p">(</span><span class="n">resource</span><span class="p">.</span><span class="n">Value</span><span class="p">)</span> <span class="p">+</span> <span class="s">&quot;&#39;,&quot;</span><span class="p">);</span>
<span class="n">PopIndent</span><span class="p">();</span>
<span class="p">}</span>
<span class="n">WriteLine</span><span class="p">(</span><span class="s">&quot;},\n&quot;</span><span class="p">);</span>
<span class="n">PopIndent</span><span class="p">();</span>
<span class="p">}</span> <span class="err">#</span><span class="p">&gt;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">resources</span><span class="p">;</span>
<span class="p">})();</span>
<span class="p">&lt;</span><span class="err">#</span><span class="p">+</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="n">GenerationEnvironment</span><span class="p">.</span><span class="n">ToString</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="err">#</span><span class="p">&gt;</span>
</pre></div>
</td></tr></table>
<p>Now it&#39;s time to add something to resource files and test if everything works fine. To run T4, just save template or use transform all templates option in Visual Studio 2013 menu:</p>
<p><img class="img-responsive center-block" src="http://developerabroad.com/img/transformAllT4Templates.png" alt="Transform All T4 Templates" /></p>
<p>Generated files are named in the same way as the original resources. They have culture name as part of extension, so you can load just specific culture, not all at once. Example file for default culture:</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><code class="language-javascript" data-lang="javascript"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21</code></pre></div></td><td class="code"><div class="highlight"><pre><span class="nx">webSiteCore</span><span class="p">.</span><span class="nx">Resource</span> <span class="o">=</span> <span class="p">(</span><span class="kd">function</span> <span class="p">(){</span>
<span class="kd">var</span> <span class="nx">resources</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">Account</span><span class="o">:</span> <span class="p">{</span>
<span class="nx">UsernameCannotBeEmpty</span> <span class="o">:</span> <span class="s1">&#39;Username cannot be empty&#39;</span><span class="p">,</span>
<span class="p">},</span>
<span class="nx">Administrator</span><span class="o">:</span> <span class="p">{</span>
<span class="nx">ErrorDetailServerVariablesTitle</span> <span class="o">:</span> <span class="s1">&#39;Server Variables&#39;</span><span class="p">,</span>
<span class="nx">ErrorDetailServerVariablesValue</span> <span class="o">:</span> <span class="s1">&#39;Value&#39;</span><span class="p">,</span>
<span class="nx">DashboardStorage</span> <span class="o">:</span> <span class="s1">&#39;Storage&#39;</span><span class="p">,</span>
<span class="nx">DashboardOperatingSystems</span> <span class="o">:</span> <span class="s1">&#39;Operating Systems&#39;</span><span class="p">,</span>
<span class="p">},</span>
<span class="nb">Error</span><span class="o">:</span> <span class="p">{</span>
<span class="nx">UnauthenticatedTitle</span> <span class="o">:</span> <span class="s1">&#39;Unauthenticated&#39;</span><span class="p">,</span>
<span class="p">},</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">resources</span><span class="p">;</span>
<span class="p">})();</span>
</pre></div>
</td></tr></table>
<p>With this approach, you can easily minify and bundle JavaScript files before deployment. It&#39;s also possible to use intellisense, since every time you use webSiteCore.Resource object, interpreter knows its definition. If some parts of your application are written purely in JavaScript, you can request dynamic loading of specific languages by using RequireJS. Unfortunately, this solution is not entirely perfect as well. When one of the requirements is to change localized texts after deployment of your application, you will have to regenerate JavaScript files and re upload them to the server. Full example is available on GitHub as a <a href="https://gist.github.com/jmalczak/2c615c10dadb9836cbc5">Gist</a>.</p>
<p><a href="http://malczak.net/programming/t4/resources/localization/2015/01/11/dot-net-resources-from-javascript/">Use .NET resources from JavaScript.</a> was originally published by Jakub Malczak at <a href="http://malczak.net">Jakub Malczak Developer Abroad</a> on January 11, 2015.</p></content>
</entry>
<entry>
<title type="html"><![CDATA[Using T4 templates to generate C# dictionary from SQL table values.]]></title>
<link rel="alternate" type="text/html" href="http://malczak.net/programming/t4/dictionary/2015/01/06/using-t4-templates/"/>
<id>http://malczak.net/programming/t4/dictionary/2015/01/06/using-t4-templates</id>
<published>2015-01-06T00:00:00+01:00</published>
<updated>2015-01-06T00:00:00+01:00</updated>
<author>
<name>Jakub Malczak</name>
<uri>http://malczak.net</uri>
<email>jmalczak@gmail.com</email>
</author>
<content type="html">
<p>When you store your data in a SQL relational database, it&#39;s always worth considering whether to have your dictionary entries not only in C# code, but in database as well. Thanks to that you can keep referential integrity between your data. Let me show you an example. If we would like to model our User table in the following way:</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><code class="language-sql" data-lang="sql">1
2
3
4
5</code></pre></div></td><td class="code"><div class="highlight"><pre><span class="k">CREATE</span> <span class="k">TABLE</span> <span class="p">[</span><span class="n">dbo</span><span class="p">].[</span><span class="k">User</span><span class="p">]</span> <span class="p">(</span>
<span class="p">[</span><span class="n">Id</span><span class="p">]</span> <span class="n">UNIQUEIDENTIFIER</span> <span class="k">NOT</span> <span class="k">NULL</span><span class="p">,</span>
<span class="p">[</span><span class="n">Name</span><span class="p">]</span> <span class="n">NVARCHAR</span> <span class="p">(</span><span class="mi">256</span><span class="p">)</span> <span class="k">NULL</span><span class="p">,</span>
<span class="p">[</span><span class="n">StatusId</span><span class="p">]</span> <span class="n">UNIQUEIDENTIFIER</span> <span class="k">NOT</span> <span class="k">NULL</span><span class="p">,</span>
<span class="p">)</span>
</pre></div>
</td></tr></table>
<p>As you can see, we have a simple user with Id, Name and user status. Since status is just a simple GUID, you can insert whatever you want there, except NULL. You probably have some kind of a guard clause in your C# code which prevents you from inserting invalid data. But wouldn&#39;t be cool if we could use SQL referential integrity to make sure that data will be consistent, even if you would like to insert row manually? To do that, we can add another table called UserStatus:</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><code class="language-sql" data-lang="sql">1
2
3
4</code></pre></div></td><td class="code"><div class="highlight"><pre><span class="k">CREATE</span> <span class="k">TABLE</span> <span class="p">[</span><span class="n">dbo</span><span class="p">].[</span><span class="n">UserStatus</span><span class="p">]</span> <span class="p">(</span>
<span class="p">[</span><span class="n">Id</span><span class="p">]</span> <span class="n">UNIQUEIDENTIFIER</span> <span class="k">NOT</span> <span class="k">NULL</span><span class="p">,</span>
<span class="p">[</span><span class="n">Name</span><span class="p">]</span> <span class="n">NVARCHAR</span> <span class="p">(</span><span class="mi">256</span><span class="p">)</span> <span class="k">NULL</span><span class="p">,</span>
<span class="p">)</span>
</pre></div>
</td></tr></table>
<p>And now we can add a foreign key from User to UserStatus table. This is done by adding the following line to User table definition:</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><code class="language-sql" data-lang="sql">1</code></pre></div></td><td class="code"><div class="highlight"><pre><span class="k">CONSTRAINT</span> <span class="p">[</span><span class="n">FK_dbo</span><span class="p">.</span><span class="n">User_dbo</span><span class="p">.</span><span class="n">UserStatus_StatusId</span><span class="p">]</span> <span class="k">FOREIGN</span> <span class="k">KEY</span> <span class="p">([</span><span class="n">StatusId</span><span class="p">])</span> <span class="k">REFERENCES</span> <span class="p">[</span><span class="n">dbo</span><span class="p">].[</span><span class="n">UserStatus</span><span class="p">]([</span><span class="n">Id</span><span class="p">])</span>
</pre></div>
</td></tr></table>
<p>If you will try to insert a new user with StatusId not in UserStatus table, you will receive an error. Now everything is fine, but you have to keep 2 copies of user status, one in your C# code in form of enum or more complex dictionary class, and the second one in your database. It&#39;s often the case that those 2 copies are out of sync. To get rid of this problem we will keep only one copy of user statuses and we will generate C# class which will be used in our C# code. T4 template fits perfectly for this kind of a job. First of all, let&#39;s make sure that all user statuses are inserted into database table. To do this, we can create SQL post deployment script which will be used to either add or edit statuses. Script can look like this:</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><code class="language-sql" data-lang="sql">1
2
3
4
5
6
7</code></pre></div></td><td class="code"><div class="highlight"><pre><span class="k">DECLARE</span> <span class="o">@</span><span class="n">Id</span> <span class="n">UNIQUEIDENTIFIER</span>
<span class="k">SET</span> <span class="o">@</span><span class="n">Id</span> <span class="o">=</span> <span class="s1">&#39;B58100F1-B66B-4FC1-B9AC-37DE29FA3C08&#39;</span>
<span class="n">IF</span> <span class="k">NOT</span> <span class="k">EXISTS</span> <span class="p">(</span><span class="k">SELECT</span> <span class="n">TOP</span> <span class="mi">1</span> <span class="mi">1</span> <span class="k">FROM</span> <span class="p">[</span><span class="n">dbo</span><span class="p">].[</span><span class="n">UserStatus</span><span class="p">]</span> <span class="k">WHERE</span> <span class="p">[</span><span class="n">Id</span><span class="p">]</span> <span class="o">=</span> <span class="o">@</span><span class="n">Id</span><span class="p">)</span>
<span class="k">BEGIN</span>
<span class="k">INSERT</span> <span class="k">INTO</span> <span class="p">[</span><span class="n">dbo</span><span class="p">].[</span><span class="n">UserStatus</span><span class="p">](</span><span class="n">Id</span><span class="p">,</span> <span class="n">Name</span><span class="p">,</span> <span class="n">InsertDate</span><span class="p">,</span> <span class="n">InsertUser</span><span class="p">)</span> <span class="k">VALUES</span> <span class="p">(</span><span class="o">@</span><span class="n">Id</span><span class="p">,</span> <span class="s1">&#39;New&#39;</span><span class="p">,</span> <span class="n">GETUTCDATE</span><span class="p">(),</span> <span class="s1">&#39;malczak.net&#39;</span><span class="p">);</span>
<span class="k">END</span>
</pre></div>
</td></tr></table>
<p>Next step is to create T4 template to generate C# classes based on data in dictionary table. We need a way to tell our template which tables are the dictionary tables and which column will be used as Id and which one as Name. Simple XML file can hold that information:</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><code class="language-xml" data-lang="xml">1
2
3
4</code></pre></div></td><td class="code"><div class="highlight"><pre><span class="cp">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;</span>
<span class="nt">&lt;dictionaries&gt;</span>
<span class="nt">&lt;dictionary</span> <span class="na">table=</span><span class="s">&quot;dbo.UserStatus&quot;</span> <span class="na">idcolumn=</span><span class="s">&quot;Id&quot;</span> <span class="na">namecolumn=</span><span class="s">&quot;Name&quot;</span> <span class="na">dictionaryname=</span><span class="s">&quot;UserStatus&quot;</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;/dictionaries&gt;</span>
</pre></div>
</td></tr></table>
<p>Additional dictionaryname attribute will be used to name C# class so it doesn&#39;t have to follow the same name as database table. Three more DTO classes are used to hold the intermediate values during dictionary generation.</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><code class="language-csharp" data-lang="csharp"> 1
2
3
4
5
6
7
8
9
10</code></pre></div></td><td class="code"><div class="highlight"><pre><span class="k">public</span> <span class="k">class</span> <span class="nc">DictionaryItemDefinition</span>
<span class="p">{</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">TableName</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">IdColumn</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">NameColumn</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">Name</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span>
</pre></div>
</td></tr></table>
<p>This is the class which is used to store data from XML file. Each row in XML is parsed and returned as DictionaryItemDefinition object.</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><code class="language-csharp" data-lang="csharp"> 1
2
3
4
5
6
7
8
9
10
11</code></pre></div></td><td class="code"><div class="highlight"><pre><span class="k">public</span> <span class="k">class</span> <span class="nc">DictionaryTable</span>
<span class="p">{</span>
<span class="k">public</span> <span class="nf">DictionaryTable</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="n">Items</span> <span class="p">=</span> <span class="k">new</span> <span class="n">List</span><span class="p">&lt;</span><span class="n">DictionaryItem</span><span class="p">&gt;();</span>
<span class="p">}</span>
<span class="k">public</span> <span class="n">Type</span> <span class="n">IdType</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="n">List</span><span class="p">&lt;</span><span class="n">DictionaryItem</span><span class="p">&gt;</span> <span class="n">Items</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span>
</pre></div>
</td></tr></table>
<p>DictionaryTable class represents table with the list of dictionary entries. So in our example this is the instance which is holding UserStatus table and New value as DictionaryItem.</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><code class="language-csharp" data-lang="csharp">1
2
3
4
5
6</code></pre></div></td><td class="code"><div class="highlight"><pre><span class="k">public</span> <span class="k">class</span> <span class="nc">DictionaryItem</span>
<span class="p">{</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">Name</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="kt">object</span> <span class="n">Id</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span>
</pre></div>
</td></tr></table>
<p>And last one holds dictionary values, so in our case name New and proper GUID value. All those classes are used in DbDictionaryHelper. Since it&#39;s much nicer to write in C# code in C# classes not in T4 templates, most of the code is encapsulated in DbDictionaryHelper. Then GetDictionaryDefinitionItems() helper method is used in T4 template to parse XML file and retrieve dictionary definition:</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><code class="language-csharp" data-lang="csharp"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15</code></pre></div></td><td class="code"><div class="highlight"><pre><span class="k">public</span> <span class="n">List</span><span class="p">&lt;</span><span class="n">DictionaryItemDefinition</span><span class="p">&gt;</span> <span class="n">GetDictionaryDefinitionItems</span><span class="p">()</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">document</span> <span class="p">=</span> <span class="n">XDocument</span><span class="p">.</span><span class="n">Load</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="n">configFilePath</span><span class="p">);</span>
<span class="k">return</span> <span class="n">Enumerable</span><span class="p">.</span><span class="n">ToList</span><span class="p">&lt;</span><span class="n">DictionaryItemDefinition</span><span class="p">&gt;(</span><span class="n">document</span><span class="p">.</span><span class="n">Descendants</span><span class="p">()</span>
<span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">n</span> <span class="p">=&gt;</span> <span class="n">n</span><span class="p">.</span><span class="n">Name</span> <span class="p">==</span> <span class="s">&quot;dictionary&quot;</span><span class="p">)</span>
<span class="p">.</span><span class="n">Select</span><span class="p">(</span><span class="n">n</span> <span class="p">=&gt;</span>
<span class="k">new</span> <span class="n">DictionaryItemDefinition</span>
<span class="p">{</span>
<span class="n">TableName</span> <span class="p">=</span> <span class="n">n</span><span class="p">.</span><span class="n">Attribute</span><span class="p">(</span><span class="s">&quot;table&quot;</span><span class="p">).</span><span class="n">Value</span><span class="p">.</span><span class="n">ToString</span><span class="p">(</span><span class="n">CultureInfo</span><span class="p">.</span><span class="n">InvariantCulture</span><span class="p">),</span>
<span class="n">IdColumn</span> <span class="p">=</span> <span class="n">n</span><span class="p">.</span><span class="n">Attribute</span><span class="p">(</span><span class="s">&quot;idcolumn&quot;</span><span class="p">).</span><span class="n">Value</span><span class="p">.</span><span class="n">ToString</span><span class="p">(</span><span class="n">CultureInfo</span><span class="p">.</span><span class="n">InvariantCulture</span><span class="p">),</span>
<span class="n">NameColumn</span> <span class="p">=</span> <span class="n">n</span><span class="p">.</span><span class="n">Attribute</span><span class="p">(</span><span class="s">&quot;namecolumn&quot;</span><span class="p">).</span><span class="n">Value</span><span class="p">.</span><span class="n">ToString</span><span class="p">(</span><span class="n">CultureInfo</span><span class="p">.</span><span class="n">InvariantCulture</span><span class="p">),</span>
<span class="n">Name</span> <span class="p">=</span> <span class="n">n</span><span class="p">.</span><span class="n">Attribute</span><span class="p">(</span><span class="s">&quot;dictionaryname&quot;</span><span class="p">).</span><span class="n">Value</span><span class="p">.</span><span class="n">ToString</span><span class="p">(</span><span class="n">CultureInfo</span><span class="p">.</span><span class="n">InvariantCulture</span><span class="p">)</span>
<span class="p">}));</span>
<span class="p">}</span>
</pre></div>
</td></tr></table>
<p>For each entry we will query corresponding table in database and get values for columns specified as Id and Name in GetDictionaryTable() method:</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><code class="language-csharp" data-lang="csharp"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28</code></pre></div></td><td class="code"><div class="highlight"><pre><span class="k">public</span> <span class="n">DictionaryTable</span> <span class="nf">GetDictionaryTable</span><span class="p">(</span><span class="n">DictionaryItemDefinition</span> <span class="n">itemDefinition</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">using</span> <span class="p">(</span><span class="kt">var</span> <span class="n">connection</span> <span class="p">=</span> <span class="k">new</span> <span class="n">SqlConnection</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="n">WebSiteCoreConnectionString</span><span class="p">))</span>
<span class="p">{</span>
<span class="k">using</span> <span class="p">(</span><span class="kt">var</span> <span class="n">command</span> <span class="p">=</span> <span class="k">new</span> <span class="n">SqlCommand</span><span class="p">(</span><span class="kt">string</span><span class="p">.</span><span class="n">Format</span><span class="p">(</span><span class="n">CultureInfo</span><span class="p">.</span><span class="n">InvariantCulture</span><span class="p">,</span> <span class="s">&quot;SELECT * FROM {0}&quot;</span><span class="p">,</span> <span class="n">itemDefinition</span><span class="p">.</span><span class="n">TableName</span><span class="p">),</span> <span class="n">connection</span><span class="p">))</span>
<span class="p">{</span>
<span class="n">connection</span><span class="p">.</span><span class="n">Open</span><span class="p">();</span>
<span class="kt">var</span> <span class="n">reader</span> <span class="p">=</span> <span class="k">new</span> <span class="n">SqlDataAdapter</span><span class="p">(</span><span class="n">command</span><span class="p">);</span>
<span class="k">using</span> <span class="p">(</span><span class="kt">var</span> <span class="n">dataSet</span> <span class="p">=</span> <span class="k">new</span> <span class="n">DataSet</span><span class="p">())</span>
<span class="p">{</span>
<span class="n">reader</span><span class="p">.</span><span class="n">Fill</span><span class="p">(</span><span class="n">dataSet</span><span class="p">);</span>
<span class="kt">var</span> <span class="n">dictionaryTable</span> <span class="p">=</span> <span class="k">new</span> <span class="n">DictionaryTable</span> <span class="p">{</span> <span class="n">IdType</span> <span class="p">=</span> <span class="n">dataSet</span><span class="p">.</span><span class="n">Tables</span><span class="p">[</span><span class="m">0</span><span class="p">].</span><span class="n">Rows</span><span class="p">[</span><span class="m">0</span><span class="p">][</span><span class="m">0</span><span class="p">].</span><span class="n">GetType</span><span class="p">()</span> <span class="p">};</span>
<span class="k">foreach</span> <span class="p">(</span><span class="n">DataRow</span> <span class="n">row</span> <span class="k">in</span> <span class="n">dataSet</span><span class="p">.</span><span class="n">Tables</span><span class="p">[</span><span class="m">0</span><span class="p">].</span><span class="n">Rows</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">dictionaryTable</span><span class="p">.</span><span class="n">Items</span><span class="p">.</span><span class="n">Add</span><span class="p">(</span><span class="k">new</span> <span class="n">DictionaryItem</span>
<span class="p">{</span>
<span class="n">Id</span> <span class="p">=</span> <span class="n">row</span><span class="p">[</span><span class="n">itemDefinition</span><span class="p">.</span><span class="n">IdColumn</span><span class="p">],</span>
<span class="n">Name</span> <span class="p">=</span> <span class="n">row</span><span class="p">[</span><span class="n">itemDefinition</span><span class="p">.</span><span class="n">NameColumn</span><span class="p">].</span><span class="n">ToString</span><span class="p">().</span><span class="n">Replace</span><span class="p">(</span><span class="s">&quot; &quot;</span><span class="p">,</span> <span class="kt">string</span><span class="p">.</span><span class="n">Empty</span><span class="p">)</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">dictionaryTable</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
</td></tr></table>
<p>Having DbDictionaryHelper, we can finally create DbDictionary.tt template which just invoke the functionality from helper class and iterate over the results to create code blocks:</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><code class="language-csharp" data-lang="csharp"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58</code></pre></div></td><td class="code"><div class="highlight"><pre><span class="p">&lt;</span><span class="err">#@</span> <span class="n">template</span> <span class="n">debug</span><span class="p">=</span><span class="s">&quot;true&quot;</span> <span class="n">hostspecific</span><span class="p">=</span><span class="s">&quot;true&quot;</span> <span class="n">language</span><span class="p">=</span><span class="s">&quot;C#&quot;</span> <span class="err">#</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="err">#@</span> <span class="n">assembly</span> <span class="n">name</span><span class="p">=</span><span class="s">&quot;System.Core&quot;</span> <span class="err">#</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="err">#@</span> <span class="n">assembly</span> <span class="n">name</span><span class="p">=</span><span class="s">&quot;System.Data&quot;</span> <span class="err">#</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="err">#@</span> <span class="n">assembly</span> <span class="n">name</span><span class="p">=</span><span class="s">&quot;System.Configuration&quot;</span> <span class="err">#</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="err">#@</span> <span class="n">assembly</span> <span class="n">name</span><span class="p">=</span><span class="s">&quot;System.Xml&quot;</span> <span class="err">#</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="err">#@</span> <span class="n">assembly</span> <span class="n">name</span><span class="p">=</span><span class="s">&quot;$(TargetPath)&quot;</span> <span class="err">#</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="err">#@</span> <span class="n">import</span> <span class="n">namespace</span><span class="p">=</span><span class="s">&quot;WebSiteCore.Common.Models.Domain.EntityDictionary&quot;</span> <span class="err">#</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="err">#@</span> <span class="n">output</span> <span class="n">extension</span><span class="p">=</span><span class="s">&quot;.cs&quot;</span> <span class="err">#</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="err">#</span>
<span class="kt">var</span> <span class="n">dictionaryItems</span> <span class="p">=</span> <span class="k">new</span> <span class="n">DbDictionaryHelper</span><span class="p">(</span><span class="n">Host</span><span class="p">,</span>
<span class="n">Host</span><span class="p">.</span><span class="n">ResolvePath</span><span class="p">(</span><span class="s">@&quot;.\DbDictionary.xml&quot;</span><span class="p">),</span>
<span class="n">Host</span><span class="p">.</span><span class="n">ResolvePath</span><span class="p">(</span><span class="s">@&quot;..\..\..\..\WebSiteCore.Web\Web.config&quot;</span><span class="p">));</span>
<span class="err">#</span><span class="p">&gt;</span>
<span class="k">namespace</span> <span class="nn">WebSiteCore.Common.Models.Domain.EntityDictionary</span>
<span class="p">{</span>
<span class="p">&lt;</span><span class="err">#</span>
<span class="kt">var</span> <span class="n">tableDefinitions</span> <span class="p">=</span> <span class="n">dictionaryItems</span><span class="p">.</span><span class="n">GetDictionaryDefinitionItems</span><span class="p">();</span>
<span class="k">foreach</span> <span class="p">(</span><span class="kt">var</span> <span class="n">tableDefinition</span> <span class="k">in</span> <span class="n">tableDefinitions</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">table</span> <span class="p">=</span> <span class="n">dictionaryItems</span><span class="p">.</span><span class="n">GetDictionaryTable</span><span class="p">(</span><span class="n">tableDefinition</span><span class="p">);</span>
<span class="err">#</span><span class="p">&gt;</span>
<span class="k">public</span> <span class="k">class</span> <span class="err">&lt;#= </span><span class="nc">tableDefinition</span><span class="p">.</span><span class="n">Name</span> <span class="err">#</span><span class="p">&gt;</span>
<span class="p">{</span>
<span class="p">&lt;</span><span class="err">#</span>
<span class="k">foreach</span> <span class="p">(</span><span class="kt">var</span> <span class="n">item</span> <span class="k">in</span> <span class="n">table</span><span class="p">.</span><span class="n">Items</span><span class="p">)</span>
<span class="p">{</span>
<span class="err">#</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="err">#</span>
<span class="k">if</span> <span class="p">(</span><span class="n">table</span><span class="p">.</span><span class="n">Items</span><span class="p">.</span><span class="n">IndexOf</span><span class="p">(</span><span class="n">item</span><span class="p">)</span> <span class="p">!=</span> <span class="m">0</span><span class="p">)</span>
<span class="p">{</span>
<span class="err">#</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="err">#</span>
<span class="p">}</span>
<span class="err">#</span><span class="p">&gt;</span>
<span class="k">public</span> <span class="k">static</span> <span class="p">&lt;</span><span class="err">#</span><span class="p">=</span> <span class="n">tableDefinition</span><span class="p">.</span><span class="n">Name</span> <span class="err">#</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="err">#</span><span class="p">=</span> <span class="n">item</span><span class="p">.</span><span class="n">Name</span> <span class="err">#</span><span class="p">&gt;</span>
<span class="p">{</span>
<span class="k">get</span>
<span class="p">{</span>
<span class="k">return</span> <span class="k">new</span> <span class="p">&lt;</span><span class="err">#</span><span class="p">=</span> <span class="n">tableDefinition</span><span class="p">.</span><span class="n">Name</span> <span class="err">#</span><span class="p">&gt;</span> <span class="p">{</span> <span class="n">Name</span> <span class="p">=</span> <span class="s">&quot;&lt;#= item.Name #&gt;&quot;</span><span class="p">,</span> <span class="n">Id</span> <span class="p">=</span> <span class="p">&lt;</span><span class="err">#</span><span class="p">=</span> <span class="n">table</span><span class="p">.</span><span class="n">IdType</span><span class="p">.</span><span class="n">FullName</span> <span class="err">#</span><span class="p">&gt;.</span><span class="n">Parse</span><span class="p">(</span><span class="s">&quot;&lt;#=item.Id#&gt;&quot;</span><span class="p">)</span> <span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">&lt;</span><span class="err">#</span>
<span class="p">}</span>
<span class="err">#</span><span class="p">&gt;</span>
<span class="k">public</span> <span class="p">&lt;</span><span class="err">#</span><span class="p">=</span> <span class="n">table</span><span class="p">.</span><span class="n">IdType</span><span class="p">.</span><span class="n">FullName</span> <span class="err">#</span><span class="p">&gt;</span> <span class="n">Id</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">Name</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span>
<span class="p">&lt;</span><span class="cp"># if (tableDefinitions.IndexOf(tableDefinition) != tableDefinitions.Count - 1) </span>
<span class="p">{</span>
<span class="err">#</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="err">#</span> <span class="p">}</span> <span class="err">#</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="err">#</span> <span class="p">}</span> <span class="err">#</span><span class="p">&gt;</span>
<span class="p">}</span>
</pre></div>
</td></tr></table>
<p>Syntax of T4 is not among my favorites but you can get used to it if you use good editor with a proper code highlighting. Final generated class for our simple example will look like this:</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><code class="language-csharp" data-lang="csharp"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17</code></pre></div></td><td class="code"><div class="highlight"><pre><span class="k">namespace</span> <span class="nn">WebSiteCore.Common.Models.Domain.EntityDictionary</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">UserStatus</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">static</span> <span class="n">UserStatus</span> <span class="n">New</span>
<span class="p">{</span>
<span class="k">get</span>
<span class="p">{</span>
<span class="k">return</span> <span class="k">new</span> <span class="n">UserStatus</span> <span class="p">{</span> <span class="n">Name</span> <span class="p">=</span> <span class="s">&quot;New&quot;</span><span class="p">,</span> <span class="n">Id</span> <span class="p">=</span> <span class="n">System</span><span class="p">.</span><span class="n">Guid</span><span class="p">.</span><span class="n">Parse</span><span class="p">(</span><span class="s">&quot;B58100F1-B66B-4FC1-B9AC-37DE29FA3C08&quot;</span><span class="p">)</span> <span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">public</span> <span class="n">System</span><span class="p">.</span><span class="n">Guid</span> <span class="n">Id</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">Name</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
</td></tr></table>
<p>And can be used in C# code in following way:</p>