user1121267
user1121267

Reputation: 109

T4 template to implement interface

I am reading the stuff about T4 template. I am wondering if it is possible that we read from .cs file (interface) and using T4 template we can generate interface implementation?

I have seen some examples but nothing about reading from .cs file and generate another .cs file using .tt

Upvotes: 1

Views: 2044

Answers (2)

xmamat
xmamat

Reputation: 181

If you don't have the interface DLL, you can compile the .cs code directly during the T4 generation and use reflection on the resulting assembly to parse the methods for generating the implementation.

<#@ assembly name="System.Core" #>
<#@ import namespace="System.CodeDom.Compiler" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Reflection" #>
<#@ import namespace="Microsoft.CSharp" #>
<#+
public class ImplementationGenerator
{
   private Assembly interfaceAssembly;

   public ImplementationGenerator(string interfaceCsFileName, string[] additionalAssemblyNames = null)
   {
       List<string> assemblyNames = new List<string>(new string[] { "System.dll", "System.Core.dll" });
       if (null != additionalAssemblyNames)
       {
           assemblyNames.AddRange(additionalAssemblyNames);
       }
       CompilerParameters parameters = new CompilerParameters(assemblyNames.ToArray())
       {
           GenerateExecutable = false,
           IncludeDebugInformation = false,
           GenerateInMemory = true
       };
       CSharpCodeProvider csProvider = new CSharpCodeProvider();
       CompilerResults interfaceResults = csProvider.CompileAssemblyFromFile(parameters, interfaceCsFileName);
       if (interfaceResults.Errors.HasErrors)
       {
           string errorMessage = "The compiler returned the following errors:\n";
           foreach (CompilerError error in interfaceResults.Errors)
           {
               errorMessage += "\t"+error.ErrorText+"\n";
           }
           throw new Exception(errorMessage);
       }
       interfaceAssembly = interfaceResults.CompiledAssembly;
   }

   public void Generate()
   {
       //use reflection to parse interfaceAssembly methods and generate the implementation
   }
}

Upvotes: 2

Viktor Lova
Viktor Lova

Reputation: 5034

There are several ways to do this:

  1. With using of assembly and import directives to reference your dll and the namespace where your class is defined. So, you can use already compiled .NET code (for example, your project). If some types/members are private, say hello to reflection. This is cool way, because you are working with code, that can be compiled (because it's already compiled) && if .cs is dependent on another classes in assembly you can know about this classes.

  2. You can use Code Model framework to parse *.cs. You can see some example here: T4 template for generating SQL view from C# enumeration

Upvotes: 0

Related Questions