T4 template to generate interface for class

【声明】本文为AdamsLee原创,转载请注明出自围炉网并保留本文有效链接:T4 template to generate interface for class, 转载请保留本声明!
<#@ template language="C#" hostspecific="True" debug="True" #>
<#@ output extension="cs" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="System.Xml" #>
<#@ assembly name="Microsoft.VisualStudio.Shell.Interop.8.0" #>
<#@ assembly name="EnvDTE" #>
<#@ assembly name="EnvDTE80" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Text.RegularExpressions" #>
<#@ import namespace="Microsoft.VisualStudio.Shell.Interop" #>
<#@ import namespace="EnvDTE" #>
<#@ import namespace="EnvDTE80" #>
<#
//System.Diagnostics.Debugger.Launch();
 
string classFileName = "UniversalIdHelper.cs";
 
DTE dte = null;
 
var serviceProvider = Host as IServiceProvider;
if (serviceProvider != null) {
    dte = serviceProvider.GetService(typeof(SDTE)) as DTE;
}
 
// Fail if we couldn't get the DTE. This can happen when trying to run in TextTransform.exe
if (dte == null) {
    throw new Exception("T4Generator can only execute through the Visual Studio host");
}
 
var project = ((object[])dte.ActiveSolutionProjects)[0] as Project;
var targetProjectItem = project.ProjectItems.Cast<ProjectItem>().Where(r => r.Name == classFileName).FirstOrDefault();
var rootNamespace = project.Properties.Item("RootNamespace").Value.ToString();
 
if(targetProjectItem == null) {
    throw new Exception("File not found:" + classFileName + 
    ". Please select(or focus) the project where the " + classFileName + " located then try again.");
}
 
 
#>
//------------------------------------------------------------------------------
// <auto-generated>
// </auto-generated>
//------------------------------------------------------------------------------
 
using System;
 
namespace <#= rootNamespace #>
{
<# 
RecurseHandleElements(targetProjectItem.FileCodeModel.CodeElements, true);
RecurseHandleElements(targetProjectItem.FileCodeModel.CodeElements, false); 
#>
}
 
<#+ // Class feature block
private void RecurseHandleElements(CodeElements codeElements, bool genInterface)
{
    var q=codeElements.Cast<CodeElement>( );
    var functions=new List<string>();
    foreach (var element in q)
    {
        if (element is CodeFunction && functions.Contains(element.Name)==false)
        {
            WriteMapping(element as CodeFunction, genInterface);
            functions.Add(element.Name);
        }
        if(element is CodeProperty)
        {
            WriteMapping(element as CodeProperty, genInterface);
        }
        if (element is CodeInterface)
        {
            var c = (CodeInterface)element;
            RecurseHandleElements(c.Members, genInterface);
        }
        if (element is CodeClass)
        {
            var c = (CodeClass)element;
            //verify element is a project element not an external
            if (c.InfoLocation==vsCMInfoLocation.vsCMInfoLocationProject)
            {
                WriteMapping(c, genInterface);
            }
        }
        if (element is CodeNamespace)
        {
            var ns=(CodeNamespace)element;
            RecurseHandleElements(ns.Members, genInterface);
        }
    }
 
}
 
void WriteMapping(CodeClass codeClass, bool genInterface)
{
    PushIndent("\t");
    if(genInterface)
    {
        WriteLine("public interface I" + codeClass.Name + "{");
    }
    else
    {
        WriteLine("public abstract class Abstract" + codeClass.Name + " : I" + codeClass.Name + "{");
    }
    PushIndent("\t");
    RecurseHandleElements(codeClass.Children, genInterface);
    PopIndent();
    WriteLine("}");
    WriteLine(string.Empty);
    PopIndent();
}
 
void WriteMapping(CodeProperty codeProperty, bool genInterface)
{
}
 
void WriteMapping(CodeFunction codeFunction, bool genInterface)
{
    if(codeFunction.Access == vsCMAccess.vsCMAccessPublic && 
        codeFunction.FunctionKind == vsCMFunction.vsCMFunctionFunction )
    {
        StringBuilder sb = new StringBuilder();
        bool multiParam = false;
        foreach (CodeParameter2 param in codeFunction.Parameters.Cast<CodeParameter2>())
        {
            if(multiParam)
            {
                sb.Append(", ");
            }
            switch(param.ParameterKind)
            {
                case vsCMParameterKind.vsCMParameterKindOut:
                    sb.Append("out ");
                    break;
                case vsCMParameterKind.vsCMParameterKindRef:
                    sb.Append("ref ");
                    break;
                case vsCMParameterKind.vsCMParameterKindNone:
                default:
                    break;
            }
            sb.Append(param.Type.AsString);
            sb.Append(" ");
            sb.Append(param.Name);
            multiParam = true;
        }
 
        if(genInterface)
        {
            WriteLine(codeFunction.Type.AsString +" "+codeFunction.Name+"(" + sb.ToString() + ");");
        }
        else
        {
            WriteLine("public virtual " + codeFunction.Type.AsString +" "+codeFunction.Name+"(" + sb.ToString() + ") { throw new NotImplementedException(); }");
        }
    }
}
 
#>
此条目发表在未分类分类目录,贴了标签。将固定链接加入收藏夹。