Showing posts with label .Net. Show all posts
Showing posts with label .Net. Show all posts

Recap/ Summary Week #31

Every beginning of weekend, I will share a recap of the week and at the same time a summary of my streams. Those videos are at least two hour longs, so I thought a short summary to know if topic interest you could be useful. Watch only the summary or relax and enjoy the longer version that up to you!

   

Recap/ Summary of Week #30

Every beginning of weekend, I will share a recap of the week and at the same time a summary of my streams. Those videos are at least two hour longs, so I thought a short summary to know if topic interest you could be useful. Watch only the summary or relax and enjoy the longer version that up to you!

   

Lecture de la semaine #6

 

from BluPointe Blog

“to read more about the filter attribute, see bit.ly/kMPBYB
“The list of built-in MVC filters can be found here: bit.ly/jSaD5N
“Profiling Your .NET Code : bit.ly/dDXWsF
“ - Guide to Improving Code Performance in .NET: Part I” by Satesh Arveti on C# Corner (bit.ly/gyImk9)
- Writing Efficient C and C Code Optimization” by Koushik Ghosh on Code Project (bit.ly/icnYEi)
- Writing High Performance .NET Code” by Juan A Rodriguez and Simonijt Dutta from Intel (intel.ly/fvweaP)”
“Deploy sites to Windows Azure in less than 30 seconds Enables deployments to multiple Web Role instances using Web Deploy Saves Web Deploy packages & IIS configuration in Windows Azure storage to provide durability A web administrator portal for managing web sites deployed to the role The ability to upload and manage SSL certificates Simple logging and diagnostics tools.”
“Installing the WAAWR is as easy as download, extract, buildme.cmd and you’re done.”

~ Franky

Lecture de la semaine #2

 

Cloud Cover Episode 23 - AppFabric Service Bus (vidéo)

Épisode très intéressante où le Service Bus est présenté avec un exemple simple. Plus d’information sur : https://portal.appfabriclabs.com et sur CodePlex. Il est possible de télécharger des exemples à partir de CodePlex ou avec Nuget. ref : http://goo.gl/fFY1F

 

Understanding Windows Azure AppFabric Queues (vidéo)

Une autre présentation sur AppFabric, axé sur les queues. ref : http://goo.gl/U3hhZ
 

Console2 - A Better Windows Command Prompt

by Scott Hanselman
Description d’une console « DOS Prompt » génial. ref : http://goo.gl/7AMqo

 

jQAPI - Alternative jQuery Documentation - For Version 1.6

Documentation très bien faite structurée, avec des exemples et permettant des recherches. C'est le même contenu que sur jquery.com mais le contenu formaté différemment et la recherche facilitée. ref : http://jqapi.com/
 

TFS merge tools configuration

Je chercher toujours d’une fois à l’autre « LA » configuration de KDiff dans Visual Studio, maintenant je ne chercherai plus. ref : http://goo.gl/dSGdM
 

Windows Azure MSDN How To tips in one place

Le titre dit tout… ref : http://goo.gl/BirT2

 

Code snippets on blogs, are you allowed to use them in your own work? No you can not!!

Je ne savais pas… maintenant j’en sais plus sur les “code snippets” et leur utilisation. ref : http://goo.gl/lPCUq
 

Tools For jQuery Application Architecture – The Printable Chart

Présentation sur jQuery, l’architecture des applications et les outils disponibles. Ref : http://goo.gl/cz46S
Aussi disponible un livre gratuit : Essential JavaScript Design Patterns 1.1 – A Free Updated Book For Beginners. Disponible ici : http://goo.gl/D98nR

~Franky

Le MvcScaffolding expliqué par Steve Sanderson


Récemment est arrivée NuGet, avec sa panoplie de packages.  Un qui avait particulièrement attiré mon attention était le MvcScaffolding.  Ce package permet de générer du code passé sur un modèle.
Dans cet article, Steve Sanderson, explique de façon très claire comment utiliser ce puissant outil. À lire absolument!


MvcScaffolding: Standard Usage: Steve Sanderson’s blog: "MvcScaffolding: Standard Usage
MVC, ScaffoldingJanuary 13th, 2011
This post describes some of the basic functionality you get with the MvcScaffolding package as soon as you install it. First, though, let’s explain a few core concepts. Don’t worry, there aren’t too many strange new concepts…
If this is the first time you’ve heard about MvcScaffolding, check out this other introductory post first.
What is a scaffolder?"

~ Franky

Important: ASP.NET Security Vulnerability - ScottGu's Blog

Scott Gu vient de mettre sur son blogue un important message expliquant une vulnérabilité de Asp.Net, ainsi qu'une façon de contourner le problème en attendant une mise à jour.

À lire absolument si vous développez avec Asp.Net.


A few hours ago we released a Microsoft Security Advisory about a security vulnerability in ASP.NET. This vulnerability exists in all versions of ASP.NET.

This vulnerability was publically disclosed late Friday at a security conference.� We recommend that all customers immediately apply a workaround (described below) to prevent attackers from using this vulnerability against your ASP.NET applications.

What does the vulnerability enable?

An attacker using this vulnerability can request and download files within an ASP.NET Application like the web.config file (which often contains sensitive data)." [read more]

~Franky

Tutorial ClickOnce

The easy way to deploy the .Net applications

In 2007 i wrote a tutorial about ClickOnce technology.  I try many time to put it on the web, but the format was to “complexe” to be only copy-paste.  Recently some reader ask me to re-work the formatting…
So here it is I just put it as a pdf.
I hope you like it…

Tutorial ClickOne (PDF)


~Franky

Read all of ASP.NET MVC 2 in Action now while you wait for the printed book

I just read this on the Jeffrey Palermo's blog, awesome reading.  I'm in a hurry to start...
image
Read all of ASP.NET MVC 2 in Action now while you wait for the printed book : Jeffrey Palermo (.com): "First, you should place your advance order for ASP.NET MVC 2 in Action at http://manning.com/palermo2. That way, you will receive the printed book even before you see it at your local bookstore.
The entire book is finished, and we are just moving through production right now. But that doesn’t mean you have to wait to read it and learn about ASP.NET MVC 2. Since the beginning of the book project, you have been able to see the progression of the book on GitHub, our project site and version control system. That’s right, version control is for more than just code!
Head over to http://github.com/jeffreypalermo/mvc2inaction and go to the “manuscript” folder to read the entire book in Word document form. All the content is there. In fact, the Word documents for the 1st edition is there as well. You can see just how much we have expanded the 2nd edition to not only cover version 2 but also to incorporate lessons learned using the framework over the last 2 years."
References: http://jeffreypalermo.com/blog/read-all-of-asp-net-mvc-2-in-action-now-while-you-wait-for-the-printed-book/

Utiliser des template T4 avec des paramètres c'est possible

Dernièrement j'ai voulu à développer une petite application pour générer du code.  L’idée est bien simple je voulais avoir une interface me permettant de saisir quelques informations et ensuite… le code devait se généré.

Après quelques recherches, mon choix s’est porté sur Text Template Transformation Toolkit (T4) de Microsoft. Le générateur de code utilisant les T4 est inclus dans Visual Studio 2008. Donc même si rien n’est nécessaire, je conseille fortement le T4 Editor de Clarius Consulting qui affichera le code avec quelques couleurs. La version de la communauté est gratuite, la version complète est payante… on s’en doutait ;)

 

Créer un template simple

Il y a plusieurs excellents tutoriels expliquent comment utiliser les templates T4, notamment sur les blogs de Oleg Sych et Scott Hanselman.  Mais pour faire vite, voici un tout petit exemple.

  • Dans un projet Visual Studio, cliquer sur [Project] –> [Add new Item].
    • Vous pouvez sélectionner
      • La catégorie [Code Generation] et le template [File].
      • La catégorie [General] et le template [Text File].  Dans ce cas assurez-vous spécifier l’extension “.tt”.
  • Entrez le nom de votre fichier, cliquez le bouton [Add]
  • Le fichier à été ajouté a votre projet.  Double cliquez dessus.
  • À la fin du fichier ajoutez le code suivant: Nous sommes le: <#= DataTime.Now.TimeOfDay #>
  • Votre fichier devrait ressembler à:
   1: <#@ template language="C#" hostspecific="True" debug="True" #>


   2: <#@ output extension="txt" #>


   3: 


   4: <#


   5: // <copyright file="File1.tt" company="">


   6: //  Copyright © . All Rights Reserved.


   7: // </copyright>


   8:  


   9:  


  10: #>


  11:  


  12: Nous sommes le: <#= DateTime.Now.TimeOfDay #>





  • Pour voir le texte généré, il faut développer (expand) le noeud du fichier et double cliquer sur le sous-fichier.


  • Voilà!



 



Utiliser des paramètres



Il est possible de créer des templates statique ou dynamique.  Pour mon projet je voulais pouvoir passer des paramètres à la dernière seconde, donc mon template ce devait d’être dynamique.  Dans un des post de Oleg Sych ce dernier spécifie qu’un Custom Host doit être fait pour pouvoir passer des paramètres.  Cependant  je n’ai pu trouver plus de détails…  Afin de faire profiter d’autre personne de mon experience j’ai décider d’écrire ce billet.



Voici donc comment j’y suis parvenu.



 



Objectifs



En partant du “Hello world” classique je vais le personaliser pour dire bonjour à une personne en particulier.  Le nom de cette personne sera le paramètre.



 



Avant de commencer



Tout d’abord afin de pouvoir faire le Custom Host il faut avoir accès au namespace Microsoft.VisualStudio.TextTemplating qui se trouve dans le VS2880 SDK.  Donc il faut installer le Visual Studio 2008 SDK (s’il n’est pas présent sur votre poste).



Custom Host



Pour faire le Custom Host j’ai simplement pris le code de Microsoft, il servira de classe de base.





   1: //CustomT4EngineHost.cs


   2:  


   3: using System;


   4: using System.Collections.Generic;


   5: using System.Linq;


   6: using System.Text;


   7: using Microsoft.VisualStudio.TextTemplating;


   8: using System.CodeDom.Compiler;


   9: using System.IO;


  10:  


  11: namespace CustomT4


  12: {


  13:     //The text template transformation engine is responsible for running 


  14:     //the transformation process.


  15:     //The host is responsible for all input and output, locating files, 


  16:     //and anything else related to the external environment.


  17:     //-------------------------------------------------------------------------


  18:     [Serializable]


  19:     public class CustomT4EngineHost : MarshalByRefObject, ITextTemplatingEngineHost


  20:     {


  21:  


  22:  


  23:         //the path and file name of the text template that is being processed


  24:         //---------------------------------------------------------------------


  25:         public string TemplateFile


  26:         {


  27:             get { return ""; }


  28:         }


  29:  


  30:  


  31:         //This will be the extension of the generated text output file.


  32:         //The host can provide a default by setting the value of the field here.


  33:         //The engine can change this value based on the optional output directive


  34:         //if the user specifies it in the text template.


  35:         //---------------------------------------------------------------------


  36:         private string fileExtensionValue = ".txt";


  37:         public string FileExtension


  38:         {


  39:             get { return fileExtensionValue; }


  40:         }


  41:  


  42:  


  43:         //This will be the encoding of the generated text output file.


  44:         //The host can provide a default by setting the value of the field here.


  45:         //The engine can change this value based on the optional output directive


  46:         //if the user specifies it in the text template.


  47:         //---------------------------------------------------------------------


  48:         private Encoding fileEncodingValue = Encoding.UTF8;


  49:         public Encoding FileEncoding


  50:         {


  51:             get { return fileEncodingValue; }


  52:         }


  53:  


  54:         //These are the errors that occur when the engine processes a template.


  55:         //The engine passes the errors to the host when it is done processing,


  56:         //and the host can decide how to display them. For example, the host 


  57:         //can display the errors in the UI or write them to a file.


  58:         //---------------------------------------------------------------------


  59:         private CompilerErrorCollection errorsValue;


  60:         public CompilerErrorCollection Errors


  61:         {


  62:             get { return errorsValue; }


  63:         }


  64:  


  65:  


  66:         //The host can provide standard assembly references.


  67:         //The engine will use these references when compiling and


  68:         //executing the generated transformation class.


  69:         //--------------------------------------------------------------


  70:         public IList<string> StandardAssemblyReferences


  71:         {


  72:             get


  73:             {


  74:                 return new string[]


  75:                 {


  76:                     //If this host searches standard paths and the GAC,


  77:                     //we can specify the assembly name like this.


  78:                     //---------------------------------------------------------


  79:                     //"System"


  80:  


  81:                     //Because this host only resolves assemblies from the 


  82:                     //fully qualified path and name of the assembly,


  83:                     //this is a quick way to get the code to give us the


  84:                     //fully qualified path and name of the System assembly.


  85:                     //---------------------------------------------------------


  86:                     typeof(System.Uri).Assembly.Location


  87:                 };


  88:             }


  89:         }


  90:  


  91:  


  92:         //The host can provide standard imports or using statements.


  93:         //The engine will add these statements to the generated 


  94:         //transformation class.


  95:         //--------------------------------------------------------------


  96:         public IList<string> StandardImports


  97:         {


  98:             get


  99:             {


 100:                 return new string[]


 101:                 {


 102:                     "System"


 103:                 };


 104:             }


 105:         }


 106:  


 107:  


 108:         //The engine calls this method based on the optional include directive


 109:         //if the user has specified it in the text template.


 110:         //This method can be called 0, 1, or more times.


 111:         //---------------------------------------------------------------------


 112:         //The included text is returned in the context parameter.


 113:         //If the host searches the registry for the location of include files,


 114:         //or if the host searches multiple locations by default, the host can


 115:         //return the final path of the include file in the location parameter.


 116:         //---------------------------------------------------------------------


 117:         public bool LoadIncludeText(string requestFileName, out string content, out string location)


 118:         {


 119:             content = System.String.Empty;


 120:             location = System.String.Empty;


 121:  


 122:             //If the argument is the fully qualified path of an existing file,


 123:             //then we are done.


 124:             //----------------------------------------------------------------


 125:             if (File.Exists(requestFileName))


 126:             {


 127:                 content = File.ReadAllText(requestFileName);


 128:                 return true;


 129:             }


 130:  


 131:             //This can be customized to search specific paths for the file.


 132:             //This can be customized to accept paths to search as command line


 133:             //arguments.


 134:             //----------------------------------------------------------------


 135:             else


 136:             {


 137:                 return false;


 138:             }


 139:         }


 140:  


 141:  


 142:         //Passes in the name of a service. If you have that service, you need to 


 143:         //pass back a pointer to it. Otherwise, you need to pass back NULL to 


 144:         //indicate that you have no knowledge of that service.


 145:         //--------------------------------------------------------------------


 146:         public object GetHostOption(string optionName)


 147:         {


 148:             object returnObject;


 149:             switch (optionName)


 150:             {


 151:                 case "CacheAssemblies":


 152:                     returnObject = true;


 153:                     break;


 154:                 default:


 155:                     returnObject = null;


 156:                     break;


 157:             }


 158:             return returnObject;


 159:         }


 160:  


 161:  


 162:         //The engine calls this method to resolve assembly references used in


 163:         //the generated transformation class project and for the optional 


 164:         //assembly directive if the user has specified it in the text template.


 165:         //This method can be called 0, 1, or more times.


 166:         //---------------------------------------------------------------------


 167:         public string ResolveAssemblyReference(string assemblyReference)


 168:         {


 169:             //If the argument is the fully qualified path of an existing file,


 170:             //then we are done. (This does not do any work.)


 171:             //----------------------------------------------------------------


 172:             var _assemblyRef = assemblyReference;


 173:             if (_assemblyRef.EndsWith(".dll", StringComparison.InvariantCultureIgnoreCase))


 174:                 _assemblyRef = _assemblyRef.Remove(_assemblyRef.Length - 4);


 175:             if (_assemblyRef.EndsWith(".exe", StringComparison.InvariantCultureIgnoreCase))


 176:                 _assemblyRef = _assemblyRef.Remove(_assemblyRef.Length - 4);


 177:  


 178:             foreach (var _assembly in AppDomain.CurrentDomain.GetAssemblies())


 179:             {


 180:                 var _assemblyName = _assembly.GetName();


 181:                 if (String.Compare(_assemblyName.Name, _assemblyRef, true) == 0 ||


 182:                     String.Compare(_assemblyName.FullName, _assemblyRef, true) == 0)


 183:                     return _assembly.Location;


 184:             }


 185:             if (File.Exists(assemblyReference))


 186:             {


 187:                 return assemblyReference;


 188:             }


 189:  


 190:             //Maybe the assembly is in the same folder as the text template that 


 191:             //called the directive.


 192:             //----------------------------------------------------------------


 193:             string candidate = Path.Combine(Path.GetDirectoryName(this.TemplateFile), assemblyReference);


 194:             if (File.Exists(candidate))


 195:             {


 196:                 return candidate;


 197:             }


 198:  


 199:             //This can be customized to search specific paths for the file


 200:             //or to search the GAC.


 201:             //----------------------------------------------------------------


 202:  


 203:             //This can be customized to accept paths to search as command line


 204:             //arguments.


 205:             //----------------------------------------------------------------


 206:  


 207:             //If we cannot do better, return the original file name.


 208:             return "";


 209:         }


 210:  


 211:  


 212:         //The engine calls this method based on the directives the user has 


 213:         //specified in the text template.


 214:         //This method can be called 0, 1, or more times.


 215:         //---------------------------------------------------------------------


 216:         public Type ResolveDirectiveProcessor(string processorName)


 217:         {


 218:             //This host will not resolve any specific processors.


 219:  


 220:             //Check the processor name, and if it is the name of a processor the 


 221:             //host wants to support, return the type of the processor.


 222:             //---------------------------------------------------------------------


 223:             if (string.Compare(processorName, "XYZ", StringComparison.OrdinalIgnoreCase) == 0)


 224:             {


 225:                 //return typeof();


 226:             }


 227:  


 228:             //This can be customized to search specific paths for the file


 229:             //or to search the GAC


 230:  


 231:             //If the directive processor cannot be found, throw an error.


 232:             throw new Exception("Directive Processor not found");


 233:         }


 234:  


 235:  


 236:         //A directive processor can call this method if a file name does not 


 237:         //have a path.


 238:         //The host can attempt to provide path information by searching 


 239:         //specific paths for the file and returning the file and path if found.


 240:         //This method can be called 0, 1, or more times.


 241:         //---------------------------------------------------------------------


 242:         public string ResolvePath(string fileName)


 243:         {


 244:             if (fileName == null)


 245:             {


 246:                 throw new ArgumentNullException("the file name cannot be null");


 247:             }


 248:  


 249:             //If the argument is the fully qualified path of an existing file,


 250:             //then we are done


 251:             //----------------------------------------------------------------


 252:             if (File.Exists(fileName))


 253:             {


 254:                 return fileName;


 255:             }


 256:  


 257:             //Maybe the file is in the same folder as the text template that 


 258:             //called the directive.


 259:             //----------------------------------------------------------------


 260:             string candidate = Path.Combine(Path.GetDirectoryName(this.TemplateFile), fileName);


 261:             if (File.Exists(candidate))


 262:             {


 263:                 return candidate;


 264:             }


 265:  


 266:             //Look more places.


 267:             //----------------------------------------------------------------


 268:             //More code can go here...


 269:  


 270:             //If we cannot do better, return the original file name.


 271:             return fileName;


 272:         }


 273:  


 274:  


 275:         //If a call to a directive in a text template does not provide a value


 276:         //for a required parameter, the directive processor can try to get it


 277:         //from the host by calling this method.


 278:         //This method can be called 0, 1, or more times.


 279:         //---------------------------------------------------------------------


 280:         public string ResolveParameterValue(string directiveId, string processorName, string parameterName)


 281:         {


 282:             if (directiveId == null)


 283:             {


 284:                 throw new ArgumentNullException("the directiveId cannot be null");


 285:             }


 286:             if (processorName == null)


 287:             {


 288:                 throw new ArgumentNullException("the processorName cannot be null");


 289:             }


 290:             if (parameterName == null)


 291:             {


 292:                 throw new ArgumentNullException("the parameterName cannot be null");


 293:             }


 294:  


 295:             //Code to provide "hard-coded" parameter values goes here.


 296:             //This code depends on the directive processors this host will interact with.


 297:  


 298:             //If we cannot do better, return the empty string.


 299:             return String.Empty;


 300:         }


 301:  


 302:  


 303:         //The engine calls this method to change the extension of the 


 304:         //generated text output file based on the optional output directive 


 305:         //if the user specifies it in the text template.


 306:         //---------------------------------------------------------------------


 307:         public void SetFileExtension(string extension)


 308:         {


 309:             //The parameter extension has a '.' in front of it already.


 310:             //--------------------------------------------------------


 311:             fileExtensionValue = extension;


 312:         }


 313:  


 314:  


 315:         //The engine calls this method to change the encoding of the 


 316:         //generated text output file based on the optional output directive 


 317:         //if the user specifies it in the text template.


 318:         //----------------------------------------------------------------------


 319:         public void SetOutputEncoding(System.Text.Encoding encoding, bool fromOutputDirective)


 320:         {


 321:             fileEncodingValue = encoding;


 322:         }


 323:  


 324:  


 325:         //The engine calls this method when it is done processing a text


 326:         //template to pass any errors that occurred to the host.


 327:         //The host can decide how to display them.


 328:         //---------------------------------------------------------------------


 329:         public void LogErrors(CompilerErrorCollection errors)


 330:         {


 331:             errorsValue = errors;


 332:         }


 333:  


 334:  


 335:         //This is the application domain that is used to compile and run


 336:         //the generated transformation class to create the generated text output.


 337:         //----------------------------------------------------------------------


 338:         public AppDomain ProvideTemplatingAppDomain(string content)


 339:         {


 340:             //This host will provide a new application domain each time the 


 341:             //engine processes a text template.


 342:             //-------------------------------------------------------------


 343:             return AppDomain.CreateDomain("Generation App Domain");


 344:  


 345:             //This could be changed to return the current appdomain, but new 


 346:             //assemblies are loaded into this AppDomain on a regular basis.


 347:             //If the AppDomain lasts too long, it will grow indefintely, 


 348:             //which might be regarded as a leak.


 349:  


 350:             //This could be customized to cache the application domain for 


 351:             //a certain number of text template generations (for example, 10).


 352:  


 353:             //This could be customized based on the contents of the text 


 354:             //template, which are provided as a parameter for that purpose.


 355:         }


 356:  


 357:     }


 358:     


 359: }




L’idée est d’avoir une classe host dans laquel on pourra passer notre paramètre.  Comme on ne peut pas modifier la classe CustomHost on fera une classe qui hérite de Custom Host et qui implemente notre interface dans où le paramètre est défini.



Ensuite nous avons besoin d’une classe qui définisse notre parameter: CustomT4Parameter.  





   1: //CustomT4Parameter.cs


   2:  


   3: using System;


   4: using System.Collections.Generic;


   5: using System.Linq;


   6: using System.Text;


   7:  


   8: namespace CustomT4


   9: {


  10:     [Serializable]


  11:     public class CustomT4Parameter


  12:     {


  13:         public CustomT4Parameter() {}


  14:  


  15:         private string _Name;


  16:  


  17:         public string Name


  18:         {


  19:             get { return _Name; }


  20:             set { _Name = value; }


  21:         }


  22:     }


  23: }




Afin de faire notre classe host qui nous servira dans notre projet, nous avons besoin d’un Interface qui permetera d’avoir accès à notre paramètre.





   1: //ICustomT4Host.cs


   2:  


   3: using System;


   4: using System.Collections.Generic;


   5: using System.Linq;


   6: using System.Text;


   7:  


   8: namespace CustomT4


   9: {


  10:     public interface ICustomT4Host


  11:     {


  12:         CustomT4Parameter T4Parameter { get; }


  13:     }


  14: }




Rien de bien compliqué…





   1: //T4Host.cs


   2:  


   3: using System;


   4: using System.Collections.Generic;


   5: using System.Linq;


   6: using System.Text;


   7:  


   8:  


   9: namespace CustomT4


  10: {


  11:     [Serializable]


  12:     public class T4Host : CustomT4EngineHost, ICustomT4Host 


  13:     {


  14:         private CustomT4Parameter _T4Parameter;


  15:  


  16:         public T4Host(CustomT4Parameter param)


  17:         {


  18:             _T4Parameter = param;


  19:         }


  20:  


  21:         #region Members


  22:  


  23:         public CustomT4Parameter T4Parameter


  24:         {


  25:             get { return _T4Parameter; }


  26:         }


  27:  


  28:         #endregion


  29:     }


  30: }



Maintenant, il nous faut un template.  Afin d’accèder à notre paramètre il faut inclure une propriété: T4Param.  Une fois ce “Getter” fait nous pouvons avois accès aux propriété du  paramètre simplement: <#= T4Param.Name #>



   1: //Hello.tt


   2:  


   3: <#@ template language="C#" hostspecific="True"  #>


   4: <#@ assembly name="System.dll" #>


   5: <#@ assembly name="PlayWithT4.exe" #>


   6: <#@ import namespace="CustomT4" #>


   7: // <autogenerated>


   8: // This code was generated by a tool. Any changes made manually will be lost


   9: // the next time this code is regenerated.


  10: // </autogenerated>


  11:  


  12: using System;  


  13:  


  14: public class Hello<#= T4Param.Name #>


  15: {


  16:    public static void SayHello()


  17:    {


  18:       Console.WriteLine("Hello <#= T4Param.Name #>!");


  19:    }


  20: }


  21:  


  22: <#+


  23:     CustomT4Parameter T4Param


  24:     {


  25:         get { 


  26:             ICustomT4Host _host = Host as ICustomT4Host;


  27:             if(_host != null)


  28:                return _host.T4Parameter;


  29:             else


  30:                throw new InvalidOperationException("Expected to find a ClassEntry");


  31:         }


  32:     }


  33: #>




Tout est prêt, il reste seulement à faire l’appel de l’engine et lui passant le custom host et le template.  Je me suis fais un petit Helper histoire de garder le code de la forms le plus simple possible, mais ce n’est pas nécessaire…





   1: // TextTemplateHelper.cs


   2:  


   3: using System;


   4: using System.IO;


   5: using Microsoft.VisualStudio.TextTemplating;


   6: using System.Globalization;


   7:  


   8: namespace CustomT4


   9: {


  10:     [Serializable]


  11:     public class TextTemplateHelper


  12:     {


  13:         public static void ProcessTemplate(string templateFileName, string outputFileName)


  14:         {


  15:             ProcessTemplate(templateFileName, outputFileName, new CustomT4EngineHost());


  16:         }


  17:  


  18:         public static void ProcessTemplate(string templateFileName, string outputFileName, CustomT4EngineHost host)


  19:         {


  20:             string templateDirectory = Path.GetDirectoryName(templateFileName);


  21:             string outputFilePath = Path.Combine(templateDirectory, outputFileName);


  22:  


  23:             string template = File.ReadAllText(templateFileName);


  24:             Engine engine = new Engine();


  25:             string output = engine.ProcessTemplate(template, host);


  26:  


  27:             if (host.Errors.HasErrors)


  28:                 throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Cannot generate template {0}. {1} Error(s). First error is: {2}", templateFileName, host.Errors.Count, host.Errors[0]));


  29:             else


  30:                 File.WriteAllText(outputFileName, output, host.FileEncoding);


  31:         }


  32:     }


  33: }




Voilà!



~Franky



 



References