程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> ahjesus使用T4模板自動維護實體,ahjesust4模板實體

ahjesus使用T4模板自動維護實體,ahjesust4模板實體

編輯:C#入門知識

ahjesus使用T4模板自動維護實體,ahjesust4模板實體


在entity項目裡新建模板DBEntity.tt

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ include file="$(SolutionDir)\Packages\T4.TemplateFileManager.2.1.2\tools\ttinc\TemplateFilemanager.CS.ttinclude" #>
<#@ include file="$(SolutionDir)\Packages\T4.TemplateFileManager.2.1.2\tools\ttinc\DbHelper.CS.ttinclude"  #>
<#@ output extension=".txt" #>

<# 
// Recommended editor: Tangible T4 Editor (http://t4-editor.tangible-engineering.com/Download_T4Editor_Plus_ModelingTools.html)
// after save SimpleSample.tt, the output will be generated in the TestFolder of the project
var fileProperties = new FileProperties()
{
    BuildAction = BuildAction.Compile
};

var fileManager = TemplateFileManager.Create(this);
fileManager.IsAutoIndentEnabled = true;
fileManager.CanOverwriteExistingFile = true;

fileManager.StartHeader();
#>
//<summary file="$filename$" company="ldy">
//------------------------------------------------------------------------------
// <auto-generated>
//    此代碼是根據模板生成的。
//
//    手動更改此文件可能會導致應用程序中發生異常行為。
//    如果重新生成代碼,則將覆蓋對此文件的手動更改。//出自 http://www.cnblogs.com/ahjesus 尊重作者辛苦勞動成果,轉載請注明出處,謝謝!
// </auto-generated>
//------------------------------------------------------------------------------
// </summary>
<# 
fileManager.EndBlock();

var paramTmpl = ParamTextTemplate.Create(this.Host);
var session = ParamTextTemplate.GetSessionObject();
    var DbTables = DbHelper.GetDbTables(config.ConnectionString, config.DbDatabase);
    foreach(var table in DbTables){
        fileManager.StartNewFile(table.TableName + ".cs", config.NameSpace,"",fileProperties);
        session["ConnectionString"] = config.ConnectionString;
        session["DbDatabase"] = config.DbDatabase;
        session["NameSpace"] = config.NameSpace;
        session["TableName"] = table.TableName;
        string output = paramTmpl.TransformText("EntityContent.tt", session);
        this.Write(output);
    }

fileManager.Process();
#>

<#+     
public class config
{
    public static readonly string ConnectionString="Data Source=192.168.1.10;Initial Catalog=TongJi;User ID=sa;Password=123456";
    public static readonly string DbDatabase="TongJi";
    public static readonly string TableName="TAd";
    public static readonly string NameSpace="__System.Entity";
}
#>

再新建EntityContent.tt

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core.dll" #>
<#@ assembly name="System.Data.dll" #>
<#@ assembly name="System.Data.DataSetExtensions.dll" #>
<#@ assembly name="System.Xml.dll" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Xml" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Data" #>
<#@ import namespace="System.Data.SqlClient" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.IO" #>
<#@ parameter name="ConnectionString" type="System.String" #>
<#@ parameter name="DbDatabase" type="System.String" #>
<#@ parameter name="TableName" type="System.String" #>
<#@ parameter name="NameSpace" type="System.String" #>
<#@ include file="$(SolutionDir)\Packages\T4.TemplateFileManager.2.1.2\tools\ttinc\DbHelper.CS.ttinclude"  #>
<#@ output extension=".txt" #>
<#if(ConnectionString!=null&&DbDatabase!=null&&TableName!=null&&NameSpace!=null){#>
using System;
using System.Collections.Generic;
namespace <#=NameSpace#>
{        
    public class <#=TableName#> : BaseEntity
    {
        <#foreach(DbColumn column in DbHelper.GetDbColumns(ConnectionString, DbDatabase, TableName)){#>
        /// <summary>
        /// <#=GetRemark(column.Remark)#>
        /// </summary>        
        public <#=column.CSharpType#><#if(column.CommonType.IsValueType && column.IsNullable){#>?<#}#> <#=column.ColumnName#> { get; set; }
        <#}#>       
    }
}
<#}#>

<#+
public string GetRemark(string str){
    char[] strArr =str.ToCharArray();
    string newStr = "";
    foreach (char cr in strArr)
    {
    if (cr == (char)10)
    {
    newStr = newStr+cr.ToString()+"///";
    }
    else{
    newStr += cr.ToString();
    }
    }
    return newStr;
}
#>

注意到有一段

<#@ include file="$(SolutionDir)\Packages\T4.TemplateFileManager.2.1.2\tools\ttinc\TemplateFilemanager.CS.ttinclude" #>
<#@ include file="$(SolutionDir)\Packages\T4.TemplateFileManager.2.1.2\tools\ttinc\DbHelper.CS.ttinclude"  #>
在解決方案文件夾目錄下的Packages(沒有就新建)裡新建T4.TemplateFileManager.2.1.2\tools\ttinc\這個目錄

新建文件TemplateFilemanager.CS.ttinclude

<#@ assembly name="System.Data.DataSetExtensions.dll" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Xml" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Data" #>
<#@ import namespace="System.Data.SqlClient" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.IO" #>
<#+
    public class DbHelper
    {
        #region GetDbTables
        
        public static List<DbTable> GetDbTables(string connectionString, string database, string tables = null)
        {
            
            if (!string.IsNullOrEmpty(tables))
            {
                tables = string.Format(" and obj.name in ('{0}')", tables.Replace(",", "','"));
            }
            #region SQL
            string sql = string.Format(@"SELECT
                                    obj.name tablename,
                                    schem.name schemname,
                                    idx.rows,
                                    CAST
                                    (
                                        CASE 
                                            WHEN (SELECT COUNT(1) FROM sys.indexes WHERE object_id= obj.OBJECT_ID AND is_primary_key=1) >=1 THEN 1
                                            ELSE 0
                                        END 
                                    AS BIT) HasPrimaryKey                                         
                                    from {0}.sys.objects obj 
                                    inner join {0}.dbo.sysindexes idx on obj.object_id=idx.id and idx.indid<=1
                                    INNER JOIN {0}.sys.schemas schem ON obj.schema_id=schem.schema_id
                                    where type='U' {1}
                                    order by obj.name", database, tables);
            #endregion
            DataTable dt = GetDataTable(connectionString, sql);
            return dt.Rows.Cast<DataRow>().Select(row => new DbTable
            {
                TableName = row.Field<string>("tablename"),
                SchemaName = row.Field<string>("schemname"),
                Rows = row.Field<int>("rows"),
                HasPrimaryKey = row.Field<bool>("HasPrimaryKey")
            }).ToList();
        }
        #endregion

        #region GetDbColumns
        
        public static List<DbColumn> GetDbColumns(string connectionString, string database, string tableName, string schema = "dbo")
        {
            #region SQL
            string sql = string.Format(@"
                                    WITH indexCTE AS
                                    (
                                        SELECT 
                                        ic.column_id,
                                        ic.index_column_id,
                                        ic.object_id    
                                        FROM {0}.sys.indexes idx
                                        INNER JOIN {0}.sys.index_columns ic ON idx.index_id = ic.index_id AND idx.object_id = ic.object_id
                                        WHERE  idx.object_id =OBJECT_ID(@tableName) AND idx.is_primary_key=1
                                    )
                                    select
                                    colm.column_id ColumnID,
                                    CAST(CASE WHEN indexCTE.column_id IS NULL THEN 0 ELSE 1 END AS BIT) IsPrimaryKey,
                                    colm.name ColumnName,
                                    systype.name ColumnType,
                                    colm.is_identity IsIdentity,
                                    colm.is_nullable IsNullable,
                                    cast(colm.max_length as int) ByteLength,
                                    (
                                        case 
                                            when systype.name='nvarchar' and colm.max_length>0 then colm.max_length/2 
                                            when systype.name='nchar' and colm.max_length>0 then colm.max_length/2
                                            when systype.name='ntext' and colm.max_length>0 then colm.max_length/2 
                                            else colm.max_length
                                        end
                                    ) CharLength,
                                    cast(colm.precision as int) Precision,
                                    cast(colm.scale as int) Scale,
                                    prop.value Remark
                                    from {0}.sys.columns colm
                                    inner join {0}.sys.types systype on colm.system_type_id=systype.system_type_id and colm.user_type_id=systype.user_type_id
                                    left join {0}.sys.extended_properties prop on colm.object_id=prop.major_id and colm.column_id=prop.minor_id
                                    LEFT JOIN indexCTE ON colm.column_id=indexCTE.column_id AND colm.object_id=indexCTE.object_id                                        
                                    where colm.object_id=OBJECT_ID(@tableName)
                                    order by colm.column_id", database);
            #endregion
            SqlParameter param = new SqlParameter("@tableName", SqlDbType.NVarChar, 100) { Value = string.Format("{0}.{1}.{2}", database, schema, tableName) };
            DataTable dt = GetDataTable(connectionString, sql, param);
            return dt.Rows.Cast<DataRow>().Select(row => new DbColumn()
            {
                ColumnID = row.Field<int>("ColumnID"),
                IsPrimaryKey = row.Field<bool>("IsPrimaryKey"),
                ColumnName = row.Field<string>("ColumnName"),
                ColumnType = row.Field<string>("ColumnType"),
                IsIdentity = row.Field<bool>("IsIdentity"),
                IsNullable = row.Field<bool>("IsNullable"),
                ByteLength = row.Field<int>("ByteLength"),
                CharLength = row.Field<int>("CharLength"),
                Scale = row.Field<int>("Scale"),
                Remark = row["Remark"].ToString()
            }).ToList();
        }

        #endregion     


        #region GetDataTable
        
        public static DataTable GetDataTable(string connectionString, string commandText, params SqlParameter[] parms)
        {
            using (SqlConnection connection = new SqlConnection(connectionString))
            {
                SqlCommand command = connection.CreateCommand();
                command.CommandText = commandText;
                command.Parameters.AddRange(parms);
                SqlDataAdapter adapter = new SqlDataAdapter(command);

                DataTable dt = new DataTable();
                adapter.Fill(dt);

                return dt;
            }
        }

        #endregion
    }

    #region DbTable
    /// <summary>
    /// 表結構
    /// </summary>
    public sealed class DbTable
    {
        /// <summary>
        /// 表名稱
        /// </summary>
        public string TableName { get; set; }
        /// <summary>
        /// 表的架構
        /// </summary>
        public string SchemaName { get; set; }
        /// <summary>
        /// 表的記錄數
        /// </summary>
        public int Rows { get; set; }

        /// <summary>
        /// 是否含有主鍵
        /// </summary>
        public bool HasPrimaryKey { get; set; }
    }
    #endregion

    #region DbColumn
    /// <summary>
    /// 表字段結構
    /// </summary>
    public sealed class DbColumn
    {
        /// <summary>
        /// 字段ID
        /// </summary>
        public int ColumnID { get; set; }

        /// <summary>
        /// 是否主鍵
        /// </summary>
        public bool IsPrimaryKey { get; set; }

        /// <summary>
        /// 字段名稱
        /// </summary>
        public string ColumnName { get; set; }

        /// <summary>
        /// 字段類型
        /// </summary>
        public string ColumnType { get; set; }

        /// <summary>
        /// 數據庫類型對應的C#類型
        /// </summary>
        public string CSharpType
        {
            get
            {
                return SqlServerDbTypeMap.MapCsharpType(ColumnType);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public Type CommonType
        {
            get
            {
                return SqlServerDbTypeMap.MapCommonType(ColumnType);
            }
        }

        /// <summary>
        /// 字節長度
        /// </summary>
        public int ByteLength { get; set; }

        /// <summary>
        /// 字符長度
        /// </summary>
        public int CharLength { get; set; }

        /// <summary>
        /// 小數位
        /// </summary>
        public int Scale { get; set; }

        /// <summary>
        /// 是否自增列
        /// </summary>
        public bool IsIdentity { get; set; }

        /// <summary>
        /// 是否允許空
        /// </summary>
        public bool IsNullable { get; set; }

        /// <summary>
        /// 描述
        /// </summary>
        public string Remark { get; set; }
    }
    #endregion

    #region SqlServerDbTypeMap

    public class SqlServerDbTypeMap
    {
        public static string MapCsharpType(string dbtype)
        {
            if (string.IsNullOrEmpty(dbtype)) return dbtype;
            dbtype = dbtype.ToLower();
            string csharpType = "object";
            switch (dbtype)
            {
                case "bigint": csharpType = "long"; break;
                case "binary": csharpType = "byte[]"; break;
                case "bit": csharpType = "bool"; break;
                case "char": csharpType = "string"; break;
                case "date": csharpType = "DateTime"; break;
                case "datetime": csharpType = "DateTime"; break;
                case "datetime2": csharpType = "DateTime"; break;
                case "datetimeoffset": csharpType = "DateTimeOffset"; break;
                case "decimal": csharpType = "decimal"; break;
                case "float": csharpType = "double"; break;
                case "image": csharpType = "byte[]"; break;
                case "int": csharpType = "int"; break;
                case "money": csharpType = "decimal"; break;
                case "nchar": csharpType = "string"; break;
                case "ntext": csharpType = "string"; break;
                case "numeric": csharpType = "decimal"; break;
                case "nvarchar": csharpType = "string"; break;
                case "real": csharpType = "Single"; break;
                case "smalldatetime": csharpType = "DateTime"; break;
                case "smallint": csharpType = "short"; break;
                case "smallmoney": csharpType = "decimal"; break;
                case "sql_variant": csharpType = "object"; break;
                case "sysname": csharpType = "object"; break;
                case "text": csharpType = "string"; break;
                case "time": csharpType = "TimeSpan"; break;
                case "timestamp": csharpType = "byte[]"; break;
                case "tinyint": csharpType = "byte"; break;
                case "uniqueidentifier": csharpType = "Guid"; break;
                case "varbinary": csharpType = "byte[]"; break;
                case "varchar": csharpType = "string"; break;
                case "xml": csharpType = "string"; break;
                default: csharpType = "object"; break;
            }
            return csharpType;
        }
           
        public static Type MapCommonType(string dbtype)
        {
            if (string.IsNullOrEmpty(dbtype)) return Type.Missing.GetType();
            dbtype = dbtype.ToLower();
            Type commonType = typeof(object);
            switch (dbtype)
            {
                case "bigint": commonType = typeof(long); break;
                case "binary": commonType = typeof(byte[]); break;
                case "bit": commonType = typeof(bool); break;
                case "char": commonType = typeof(string); break;
                case "date": commonType = typeof(DateTime); break;
                case "datetime": commonType = typeof(DateTime); break;
                case "datetime2": commonType = typeof(DateTime); break;
                case "datetimeoffset": commonType = typeof(DateTimeOffset); break;
                case "decimal": commonType = typeof(decimal); break;
                case "float": commonType = typeof(double); break;
                case "image": commonType = typeof(byte[]); break;
                case "int": commonType = typeof(int); break;
                case "money": commonType = typeof(decimal); break;
                case "nchar": commonType = typeof(string); break;
                case "ntext": commonType = typeof(string); break;
                case "numeric": commonType = typeof(decimal); break;
                case "nvarchar": commonType = typeof(string); break;
                case "real": commonType = typeof(Single); break;
                case "smalldatetime": commonType = typeof(DateTime); break;
                case "smallint": commonType = typeof(short); break;
                case "smallmoney": commonType = typeof(decimal); break;
                case "sql_variant": commonType = typeof(object); break;
                case "sysname": commonType = typeof(object); break;
                case "text": commonType = typeof(string); break;
                case "time": commonType = typeof(TimeSpan); break;
                case "timestamp": commonType = typeof(byte[]); break;
                case "tinyint": commonType = typeof(byte); break;
                case "uniqueidentifier": commonType = typeof(Guid); break;
                case "varbinary": commonType = typeof(byte[]); break;
                case "varchar": commonType = typeof(string); break;
                case "xml": commonType = typeof(string); break;
                default: commonType = typeof(object); break;
            }
            return commonType;
        }
    }
    #endregion
    

#>

新建TemplateFilemanager.CS.ttinclude

<#@ assembly name="System.Core" #>
<#@ assembly name="System.Data" #>
<#@ assembly name="System.Data.Entity" #>
<#@ assembly name="System.Xml" #>
<#@ assembly name="System.Xml.Linq"#>
<#@ assembly name="System.Windows.Forms" #>
<#@ assembly name="EnvDTE"#>
<#@ assembly name="EnvDTE80" #>
<#@ assembly name="Microsoft.VisualStudio.Shell.10.0"#>
<#@ assembly name="Microsoft.VisualStudio.Shell.Interop "#>
<#@ import namespace="Microsoft.VisualStudio.Shell.Interop"#>
<#@ import namespace="System" #>
<#@ import namespace="System.Data" #>
<#@ import namespace="System.Data.Objects" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Data.Objects.DataClasses" #>
<#@ import namespace="System.Text.RegularExpressions" #>
<#@ import namespace="System.Xml" #>
<#@ import namespace="System.Xml.Linq" #>
<#@ import namespace="System.Globalization" #>
<#@ import namespace="System.Reflection" #>
<#@ import namespace="System.CodeDom" #>
<#@ import namespace="System.CodeDom.Compiler" #>
<#@ import namespace="Microsoft.CSharp"#>
<#@ import namespace="System.Text"#>
<#@ import namespace="EnvDTE" #>
<#@ import namespace="Microsoft.VisualStudio.TextTemplating" #>
<#+ 
/*
   This software is supplied "AS IS". The authors disclaim all warranties, 
   expressed or implied, including, without limitation, the warranties of 
   merchantability and of fitness for any purpose. The authors assume no
   liability for direct, indirect, incidental, special, exemplary, or
   consequential damages, which may result from the use of this software,
   even if advised of the possibility of such damage.

The TemplateFileManager is based on EntityFrameworkTemplateFileManager (EFTFM) from MS.

Differences to EFTFM
Version 2.1.2
- Bugfix Exception when solution contains wix-projects, reported by jturner
Version 2.1:
- Replace Enum BuildAction with class for more flexibility
Version 2:
- StartHeader works with Parameter $filename$
- StartNewFile has a new named parameter FileProperties
  - Support for:
   - BuildAction
   - CustomTool
   - user defined parameter for using in StartHeader-Block
- Property IsAutoIndentEnabled for support Format Document (C#, VB) when set to true

Version: 1.1
Add method WriteLineToBuildPane, WriteToBuildPane

Version 1:
- StartNewFile with named parameters projectName and folderName for generating files to different locations.
- Property CanOverrideExistingFile, to define whether existing files are can overwritten
- Property Encoding Encode type for output files.
*/

/// <summary>
/// Writes a line to the build pane in visual studio and activates it
/// </summary>
/// <param name="message">Text to output - a \n is appended</param>
void WriteLineToBuildPane (string message){
       WriteLineToBuildPane(String.Format("{0}\n", message));
}

/// <summary>
/// Writes a string to the build pane in visual studio and activates it
/// </summary>
/// <param name="message">Text to output</param>
void WriteToBuildPane (string message){
       IVsOutputWindow outWindow = (this.Host as IServiceProvider).GetService(
typeof( SVsOutputWindow ) ) as IVsOutputWindow;
       Guid generalPaneGuid =
Microsoft.VisualStudio.VSConstants.OutputWindowPaneGuid.BuildOutputPane_guid;
        // P.S. There's also the GUID_OutWindowDebugPane available.
       IVsOutputWindowPane generalPane;
       outWindow.GetPane( ref generalPaneGuid , out generalPane );
       generalPane.OutputString( message  );
       generalPane.Activate(); // Brings this pane into view
}

/// <summary>
/// Responsible for marking the various sections of the generation,
/// so they can be split up into separate files and projects
/// </summary>
/// <author>R. Leupold</author>
public class TemplateFileManager
{
    private EnvDTE.ProjectItem templateProjectItem;
    private Action<string> checkOutAction;
    private Action<IEnumerable<OutputFile>> projectSyncAction;
    private EnvDTE.DTE dte;
    private List<string> templatePlaceholderList = new List<string>();
    
    /// <summary>
    /// Creates files with VS sync
    /// </summary>
    public static TemplateFileManager Create(object textTransformation)
    {
        DynamicTextTransformation2 transformation = DynamicTextTransformation2.Create(textTransformation);
        IDynamicHost2 host = transformation.Host;
        return new TemplateFileManager(transformation);
    }

    private readonly List<Block> files = new List<Block>();
    private readonly Block footer = new Block();
    private readonly Block header = new Block();
    private readonly DynamicTextTransformation2 _textTransformation;

    // reference to the GenerationEnvironment StringBuilder on the
    // TextTransformation object
    private readonly StringBuilder _generationEnvironment;

    private Block currentBlock;

    /// <summary>
    /// Initializes an TemplateFileManager Instance  with the
    /// TextTransformation (T4 generated class) that is currently running
    /// </summary>
    private TemplateFileManager(object textTransformation)
    {
        if (textTransformation == null)
        {
            throw new ArgumentNullException("textTransformation");
        }
                
        _textTransformation = DynamicTextTransformation2.Create(textTransformation);
        _generationEnvironment = _textTransformation.GenerationEnvironment;
        
        var hostServiceProvider = _textTransformation.Host.AsIServiceProvider();
        if (hostServiceProvider == null)
        {
            throw new ArgumentNullException("Could not obtain hostServiceProvider");
        }

        dte = (EnvDTE.DTE) hostServiceProvider.GetService(typeof(EnvDTE.DTE));
        if (dte == null)
        {
            throw new ArgumentNullException("Could not obtain DTE from host");
        }
        
        this.templateProjectItem = dte.Solution.FindProjectItem(_textTransformation.Host.TemplateFile);
        this.CanOverrideExistingFile = true;
        this.IsAutoIndentEnabled = false;
        this.Encoding = System.Text.Encoding.UTF8;
        checkOutAction = fileName => dte.SourceControl.CheckOutItem(fileName);
        projectSyncAction = keepFileNames => ProjectSync(templateProjectItem, keepFileNames);
    }

    /// <summary>
    /// If set to false, existing files are not overwritten
    /// </summary>
    /// <returns></returns>
    public bool CanOverrideExistingFile { get; set; }
    public bool CanOverwriteExistingFile { get { return this.CanOverrideExistingFile; } set { this.CanOverrideExistingFile = value;} }
    
    /// <summary>
    /// If set to true, output files (c#, vb) are formatted based on the vs settings.
    /// </summary>
    /// <returns></returns>
    public bool IsAutoIndentEnabled { get; set; }
    
    /// <summary>
    /// Defines Encoding format for generated output file. (Default UTF8)
    /// </summary>
    /// <returns></returns>
    public System.Text.Encoding Encoding { get; set; }
    
    /// <summary>
    /// Marks the end of the last file if there was one, and starts a new
    /// and marks this point in generation as a new file.
    /// </summary>
    /// <param name="name">Filename</param>
    /// <param name="projectName">Name of the target project for the new file.</param>
    /// <param name="folderName">Name of the target folder for the new file.</param>
    /// <param name="fileProperties">File property settings in vs for the new File</param>
    public void StartNewFile(string name
        , string projectName = "", string folderName = "", FileProperties fileProperties = null)
    {
        if (String.IsNullOrWhiteSpace(name) == true)
        {
            throw new ArgumentException("name");
        }

        CurrentBlock = new Block 
                      { 
                        Name = name, 
                        ProjectName = projectName, 
                        FolderName = folderName,
                        FileProperties = fileProperties ?? new FileProperties()
                      };
    }

    public void StartFooter()
    {
        CurrentBlock = footer;
    }

    public void StartHeader()
    {
        CurrentBlock = header;
    }

    public void EndBlock()
    {
        if (CurrentBlock == null)
        {
            return;
        }

        CurrentBlock.Length = _generationEnvironment.Length - CurrentBlock.Start;

        if (CurrentBlock != header && CurrentBlock != footer)
        {
            files.Add(CurrentBlock);
        }

        currentBlock = null;
    }
    
    /// <summary>
    /// Produce the template output files.
    /// </summary>
    public virtual IEnumerable<OutputFile> Process(bool split = true)
    {
        var list = new List<OutputFile>();
        
        if (split)
        {
            EndBlock();

            var headerText = _generationEnvironment.ToString(header.Start, header.Length);
            var footerText = _generationEnvironment.ToString(footer.Start, footer.Length);
            files.Reverse();

            foreach (var block in files)
            {
                var outputPath = VSHelper.GetOutputPath(dte, block, Path.GetDirectoryName(_textTransformation.Host.TemplateFile));
                var fileName = Path.Combine(outputPath, block.Name);
                var content = this.ReplaceParameter(headerText, block) + 
                _generationEnvironment.ToString(block.Start, block.Length) + 
                footerText;

                var file = new OutputFile 
                   { 
                        FileName = fileName, 
                        ProjectName = block.ProjectName, 
                        FolderName = block.FolderName,
                        FileProperties = block.FileProperties,
                        Content = content
                    };
                
                CreateFile(file);
                _generationEnvironment.Remove(block.Start, block.Length);
                                
                list.Add(file);        
            }
        }
        
        projectSyncAction.EndInvoke(projectSyncAction.BeginInvoke(list, null, null));
        this.CleanUpTemplatePlaceholders();
        var items = VSHelper.GetOutputFilesAsProjectItems(this.dte, list);
        this.WriteVsProperties(items, list);
        
        if (this.IsAutoIndentEnabled == true && split == true)
        {
            this.FormatProjectItems(items);
        }
            
        this.WriteLog(list);
        
        return list;
    }
    
    private void FormatProjectItems(IEnumerable<EnvDTE.ProjectItem> items)
    {
        foreach (var item in items)
        {
            this._textTransformation.WriteLine(
            VSHelper.ExecuteVsCommand(this.dte, item, "Edit.FormatDocument")); //, "Edit.RemoveAndSort"));
            this._textTransformation.WriteLine("//-> " + item.Name);
        }
    }
    
    private void WriteVsProperties(IEnumerable<EnvDTE.ProjectItem> items, IEnumerable<OutputFile> outputFiles)
    {
        foreach (var file in outputFiles)
        {
            var item = items.Where(p => p.Name == Path.GetFileName(file.FileName)).FirstOrDefault();
            if (item == null) continue; 
            
            if (String.IsNullOrEmpty(file.FileProperties.CustomTool) == false)
            {
                VSHelper.SetPropertyValue(item, "CustomTool", file.FileProperties.CustomTool);
            }

            if (String.IsNullOrEmpty(file.FileProperties.BuildActionString) == false)
            {
                VSHelper.SetPropertyValue(item, "ItemType", file.FileProperties.BuildActionString);
            }
        }
    }
    
    private string ReplaceParameter(string text, Block block)
    {
        if (String.IsNullOrEmpty(text) == false)
        {
            text = text.Replace("$filename$", block.Name);
        }
        
        
        foreach (var item in block.FileProperties.TemplateParameter.AsEnumerable())
        {
            text = text.Replace(item.Key, item.Value);
        }
        
        return text;
    }
    
    /// <summary>
    /// Write log to the default output file.
    /// </summary>
    /// <param name="list"></param>
    private void WriteLog(IEnumerable<OutputFile> list)
    {
        this._textTransformation.WriteLine("// Generated helper templates");
        foreach (var item in templatePlaceholderList)
        {
            this._textTransformation.WriteLine("// " + this.GetDirectorySolutionRelative(item));         
        }
        
        this._textTransformation.WriteLine("// Generated items");
        foreach (var item in list)
        {
            this._textTransformation.WriteLine("// " + this.GetDirectorySolutionRelative(item.FileName)); 
        }
    }
    
    /// <summary>
    /// Removes old template placeholders from the solution.
    /// </summary>
    private void CleanUpTemplatePlaceholders()        
    {
        string[] activeTemplateFullNames = this.templatePlaceholderList.ToArray();
        string[] allHelperTemplateFullNames = VSHelper.GetAllSolutionItems(this.dte)
            .Where(p => p.Name == VSHelper.GetTemplatePlaceholderName(this.templateProjectItem))
            .Select(p => VSHelper.GetProjectItemFullPath(p))
            .ToArray();
        
        var delta = allHelperTemplateFullNames.Except(activeTemplateFullNames).ToArray();
            
        var dirtyHelperTemplates = VSHelper.GetAllSolutionItems(this.dte)
            .Where(p => delta.Contains(VSHelper.GetProjectItemFullPath(p)));

        foreach (ProjectItem item in dirtyHelperTemplates)
        {
            if (item.ProjectItems != null)
            {
                foreach (ProjectItem subItem in item.ProjectItems)
                {
                    subItem.Remove(); 
                }
            }
            
            item.Remove();
        }
    }
    
    /// <summary>
    /// Gets a list of helper templates from the log.
    /// </summary>
    /// <returns>List of generated helper templates.</returns>
    private string[] GetPreviousTemplatePlaceholdersFromLog()
    {
        string path = Path.GetDirectoryName(this._textTransformation.Host.ResolvePath(this._textTransformation.Host.TemplateFile));
        string file1 = Path.GetFileNameWithoutExtension(this._textTransformation.Host.TemplateFile) + ".txt";
        string contentPrevious = File.ReadAllText(Path.Combine(path, file1));
        
        var result = contentPrevious
              .Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries)
              .Select(x => x.Split(new[] { "=>" }, StringSplitOptions.RemoveEmptyEntries).First())
              .Select(x => Regex.Replace(x, "//", String.Empty).Trim())
              .Where(x => x.EndsWith(VSHelper.GetTemplatePlaceholderName(this.templateProjectItem)))
              .ToArray();
        
        return result;
    }
    
    private string GetDirectorySolutionRelative(string fullName)
    {
        int slnPos = fullName.IndexOf(Path.GetFileNameWithoutExtension(this.dte.Solution.FileName));
        if (slnPos < 0)
        {
            slnPos = 0;
        }
        
        return fullName.Substring(slnPos);
    }
    
    protected virtual void CreateFile(OutputFile file)
    {
        if (this.CanOverrideExistingFile == false && File.Exists(file.FileName) == true)
        {
            return;
        }
        
        if (IsFileContentDifferent(file))
        {
            CheckoutFileIfRequired(file.FileName);
            File.WriteAllText(file.FileName, file.Content, this.Encoding);
        }
    }

    protected bool IsFileContentDifferent(OutputFile file)
    {
        return !(File.Exists(file.FileName) && File.ReadAllText(file.FileName) == file.Content);
    }

    private Block CurrentBlock
    {
        get { return currentBlock; }
        set
        {
            if (CurrentBlock != null)
            {
                EndBlock();
            }

            if (value != null)
            {
                value.Start = _generationEnvironment.Length;
            }

            currentBlock = value;
        }        
    }
    
    private void ProjectSync(EnvDTE.ProjectItem templateProjectItem, IEnumerable<OutputFile> keepFileNames)
    {
        var groupedFileNames = from f in keepFileNames
                                group f by new { f.ProjectName, f.FolderName }
                                into l
                                select new { 
                                    ProjectName = l.Key.ProjectName,
                                    FolderName = l.Key.FolderName,
                                    FirstItem = l.First(),
                                    OutputFiles = l
                                };
        
        this.templatePlaceholderList.Clear();
                                
        foreach (var item in groupedFileNames)
        {
            EnvDTE.ProjectItem pi = VSHelper.GetTemplateProjectItem(templateProjectItem.DTE, item.FirstItem, templateProjectItem);
            ProjectSyncPart(pi, item.OutputFiles);
            
            if (pi.Name.EndsWith("txt4"))
                this.templatePlaceholderList.Add(VSHelper.GetProjectItemFullPath(pi));            
        }
    
        // clean up
        bool hasDefaultItems = groupedFileNames.Where(f => String.IsNullOrEmpty(f.ProjectName) && String.IsNullOrEmpty(f.FolderName)).Count() > 0;
        if (hasDefaultItems == false)
        {
            ProjectSyncPart(templateProjectItem, new List<OutputFile>());
        }
    }
    
    private static void ProjectSyncPart(EnvDTE.ProjectItem templateProjectItem, IEnumerable<OutputFile> keepFileNames)
    {
        var keepFileNameSet = new HashSet<OutputFile>(keepFileNames);
        var projectFiles = new Dictionary<string, EnvDTE.ProjectItem>();
        var originalOutput = Path.GetFileNameWithoutExtension(templateProjectItem.FileNames[0]);

        foreach (EnvDTE.ProjectItem projectItem in templateProjectItem.ProjectItems)
        {
            projectFiles.Add(projectItem.FileNames[0], projectItem);
        }

        // Remove unused items from the project
        foreach (var pair in projectFiles)
        {
            bool isNotFound = keepFileNames.Where(f=>f.FileName == pair.Key).Count() == 0;
            if (isNotFound == true
                && !(Path.GetFileNameWithoutExtension(pair.Key) + ".").StartsWith(originalOutput + "."))
            {
                pair.Value.Delete();
            }
        }

        // Add missing files to the project
        foreach (var fileName in keepFileNameSet)
        {
            if (!projectFiles.ContainsKey(fileName.FileName))
            {
                templateProjectItem.ProjectItems.AddFromFile(fileName.FileName);
            }
        }
    }

    private void CheckoutFileIfRequired(string fileName)
    {
        if (dte.SourceControl == null
            || !dte.SourceControl.IsItemUnderSCC(fileName)
                || dte.SourceControl.IsItemCheckedOut(fileName))
        {
            return;
        }

        // run on worker thread to prevent T4 calling back into VS
        checkOutAction.EndInvoke(checkOutAction.BeginInvoke(fileName, null, null));
    }        
}

/// <summary>
/// Responsible creating an instance that can be passed
/// to helper classes that need to access the TextTransformation
/// members.  It accesses member by name and signature rather than
/// by type.  This is necessary when the
/// template is being used in Preprocessed mode
/// and there is no common known type that can be
/// passed instead
/// </summary>
public class DynamicTextTransformation2
{
    private object _instance;
    IDynamicHost2 _dynamicHost;

    private readonly MethodInfo _write;
    private readonly MethodInfo _writeLine;
    private readonly PropertyInfo _generationEnvironment;
    private readonly PropertyInfo _errors;
    private readonly PropertyInfo _host;

    /// <summary>
    /// Creates an instance of the DynamicTextTransformation class around the passed in
    /// TextTransformation shapped instance passed in, or if the passed in instance
    /// already is a DynamicTextTransformation, it casts it and sends it back.
    /// </summary>
    public static DynamicTextTransformation2 Create(object instance)
    {
        if (instance == null)
        {
            throw new ArgumentNullException("instance");
        }

        DynamicTextTransformation2 textTransformation = instance as DynamicTextTransformation2;
        if (textTransformation != null)
        {
            return textTransformation;
        }

        return new DynamicTextTransformation2(instance);
    }

    private DynamicTextTransformation2(object instance)
    {
        _instance = instance;
        Type type = _instance.GetType();
        _write = type.GetMethod("Write", new Type[] { typeof(string) });
        _writeLine = type.GetMethod("WriteLine", new Type[] { typeof(string) });
        _generationEnvironment = type.GetProperty("GenerationEnvironment", BindingFlags.Instance | BindingFlags.NonPublic);
        _host = type.GetProperty("Host");
        _errors = type.GetProperty("Errors");
    }

    /// <summary>
    /// Gets the value of the wrapped TextTranformation instance's GenerationEnvironment property
    /// </summary>
    public StringBuilder GenerationEnvironment { get { return (StringBuilder)_generationEnvironment.GetValue(_instance, null); } }

    /// <summary>
    /// Gets the value of the wrapped TextTranformation instance's Errors property
    /// </summary>
    public System.CodeDom.Compiler.CompilerErrorCollection Errors { get { return (System.CodeDom.Compiler.CompilerErrorCollection)_errors.GetValue(_instance, null); } }

    /// <summary>
    /// Calls the wrapped TextTranformation instance's Write method.
    /// </summary>
    public void Write(string text)
    {
        _write.Invoke(_instance, new object[] { text });
    }

    /// <summary>
    /// Calls the wrapped TextTranformation instance's WriteLine method.
    /// </summary>
    public void WriteLine(string text)
    {
        _writeLine.Invoke(_instance, new object[] { text });
    }

    /// <summary>
    /// Gets the value of the wrapped TextTranformation instance's Host property
    /// if available (shows up when hostspecific is set to true in the template directive) and returns
    /// the appropriate implementation of IDynamicHost
    /// </summary>
    public IDynamicHost2 Host
    {
        get
        {
            if (_dynamicHost == null)
            {
                if(_host == null)
                {
                    _dynamicHost = new NullHost2();
                }
                else
                {
                    _dynamicHost = new DynamicHost2(_host.GetValue(_instance, null));
                }
            }
            return _dynamicHost;
        }
    }
}

/// <summary>
/// Reponsible for abstracting the use of Host between times
/// when it is available and not
/// </summary>
public interface IDynamicHost2
{
    /// <summary>
    /// An abstracted call to Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost ResolveParameterValue
    /// </summary>
    string ResolveParameterValue(string id, string name, string otherName);

    /// <summary>
    /// An abstracted call to Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost ResolvePath
    /// </summary>
    string ResolvePath(string path);

    /// <summary>
    /// An abstracted call to Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost TemplateFile
    /// </summary>
    string TemplateFile { get; }

    /// <summary>
    /// Returns the Host instance cast as an IServiceProvider
    /// </summary>
    IServiceProvider AsIServiceProvider();
}

/// <summary>
/// Reponsible for implementing the IDynamicHost as a dynamic
/// shape wrapper over the Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost interface
/// rather than type dependent wrapper.  We don't use the
/// interface type so that the code can be run in preprocessed mode
/// on a .net framework only installed machine.
/// </summary>
public class DynamicHost2 : IDynamicHost2
{
    private readonly object _instance;
    private readonly MethodInfo _resolveParameterValue;
    private readonly MethodInfo _resolvePath;
    private readonly PropertyInfo _templateFile;

    /// <summary>
    /// Creates an instance of the DynamicHost class around the passed in
    /// Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost shapped instance passed in.
    /// </summary>
    public DynamicHost2(object instance)
    {
        _instance = instance;
        Type type = _instance.GetType();
        _resolveParameterValue = type.GetMethod("ResolveParameterValue", new Type[] { typeof(string), typeof(string), typeof(string) });
        _resolvePath = type.GetMethod("ResolvePath", new Type[] { typeof(string) });
        _templateFile = type.GetProperty("TemplateFile");

    }

    /// <summary>
    /// A call to Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost ResolveParameterValue
    /// </summary>
    public string ResolveParameterValue(string id, string name, string otherName)
    {
        return (string)_resolveParameterValue.Invoke(_instance, new object[] { id, name, otherName });
    }

    /// <summary>
    /// A call to Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost ResolvePath
    /// </summary>
    public string ResolvePath(string path)
    {
        return (string)_resolvePath.Invoke(_instance, new object[] { path });
    }

    /// <summary>
    /// A call to Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost TemplateFile
    /// </summary>
    public string TemplateFile
    {
        get
        {
            return (string)_templateFile.GetValue(_instance, null);
        }
    }

    /// <summary>
    /// Returns the Host instance cast as an IServiceProvider
    /// </summary>
    public IServiceProvider AsIServiceProvider()
    {
        return _instance as IServiceProvider;
    }
}

/// <summary>
/// Reponsible for implementing the IDynamicHost when the
/// Host property is not available on the TextTemplating type. The Host
/// property only exists when the hostspecific attribute of the template
/// directive is set to true.
/// </summary>
public class NullHost2 : IDynamicHost2
{
    /// <summary>
    /// An abstraction of the call to Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost ResolveParameterValue
    /// that simply retuns null.
    /// </summary>
    public string ResolveParameterValue(string id, string name, string otherName)
    {
        return null;
    }

    /// <summary>
    /// An abstraction of the call to Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost ResolvePath
    /// that simply retuns the path passed in.
    /// </summary>
    public string ResolvePath(string path)
    {
        return path;
    }

    /// <summary>
    /// An abstraction of the call to Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost TemplateFile
    /// that returns null.
    /// </summary>
    public string TemplateFile
    {
        get
        {
            return null;
        }
    }

    /// <summary>
    /// Returns null.
    /// </summary>
    public IServiceProvider AsIServiceProvider()
    {
        return null;
    }
}

public sealed class Block
{
    public String Name;
    public int Start, Length;
    public string ProjectName { get; set; }
    public string FolderName { get; set; }
    public FileProperties FileProperties { get; set; }
}

public class ParamTextTemplate
{
    private ITextTemplatingEngineHost Host { get; set; }
    
    private ParamTextTemplate(ITextTemplatingEngineHost host)
    {
        this.Host = host;
    }
    
    public static ParamTextTemplate Create(ITextTemplatingEngineHost host)
    {
        return new ParamTextTemplate(host);
    }
    
    public static TextTemplatingSession GetSessionObject()
    {
        return new TextTemplatingSession();
    }
    
    public string TransformText(string templateName, TextTemplatingSession session)
    {
        return this.GetTemplateContent(templateName, session);
    }
    
    public string GetTemplateContent(string templateName, TextTemplatingSession session)
    {
        string fullName = this.Host.ResolvePath(templateName);
        string templateContent = File.ReadAllText(fullName);
        
        var sessionHost = this.Host as ITextTemplatingSessionHost;
        sessionHost.Session = session;

        Engine engine = new Engine();
        return engine.ProcessTemplate(templateContent, this.Host);
    }
}

public class VSHelper
{
    /// <summary>
    /// Execute Visual Studio commands against the project item.
    /// </summary>
    /// <param name="item">The current project item.</param>
    /// <param name="command">The vs command as string.</param>
    /// <returns>An error message if the command fails.</returns>
    public static string ExecuteVsCommand(EnvDTE.DTE dte, EnvDTE.ProjectItem item, params string[] command)
    {
        if (item == null)
        {
            throw new ArgumentNullException("item");
        }
        
        string error = String.Empty;
        
        try
        {
            EnvDTE.Window window = item.Open();
            window.Activate();
            
            foreach (var cmd in command)
            {
                if (String.IsNullOrWhiteSpace(cmd) == true)
                {
                    continue;
                }
                
                EnvDTE80.DTE2 dte2 = dte as EnvDTE80.DTE2;
                dte2.ExecuteCommand(cmd, String.Empty);        
            }
            
            item.Save();
            window.Visible = false;
            // window.Close(); // Ends VS, but not the tab :(
        }
        catch (Exception ex)
        {
            error = String.Format("Error processing file {0} {1}", item.Name, ex.Message);
        }
        
        return error;
    }
    
    /// <summary>
    /// Sets a property value for the vs project item.
    /// </summary>
    public static void SetPropertyValue(EnvDTE.ProjectItem item, string propertyName, object value)
    {
        EnvDTE.Property property = item.Properties.Item(propertyName);
        if (property == null)
        {
            throw new ArgumentException(String.Format("The property {0} was not found.", propertyName));
        }
        else
        {
            property.Value = value;
        }
    }
    
    public static IEnumerable<ProjectItem> GetOutputFilesAsProjectItems(EnvDTE.DTE dte, IEnumerable<OutputFile> outputFiles)
    {
        var fileNames = (from o in outputFiles
                        select Path.GetFileName(o.FileName)).ToArray();

        return VSHelper.GetAllSolutionItems(dte).Where(f => fileNames.Contains(f.Name));
    }
    
    public static string GetOutputPath(EnvDTE.DTE dte, Block block, string defaultPath)
    {
        if (String.IsNullOrEmpty(block.ProjectName) == true && String.IsNullOrEmpty(block.FolderName) == true)
        {
            return defaultPath;
        }
        
        EnvDTE.Project prj = null;
        EnvDTE.ProjectItem item = null;
        
        if (String.IsNullOrEmpty(block.ProjectName) == false)
        {
            prj = GetProject(dte, block.ProjectName);            
        }
        
        if (String.IsNullOrEmpty(block.FolderName) == true && prj != null)
        {
            return Path.GetDirectoryName(prj.FullName);
        }
        else if (prj != null && String.IsNullOrEmpty(block.FolderName) == false)
        {
            item = GetAllProjectItemsRecursive(prj.ProjectItems).Where(i=>i.Name == block.FolderName).First();
        }
        else if (String.IsNullOrEmpty(block.FolderName) == false)
        {
            item = GetAllProjectItemsRecursive(
                dte.ActiveDocument.ProjectItem.ContainingProject.ProjectItems).
                Where(i=>i.Name == block.FolderName).First();
        }
        
        if (item != null)
        {
            return GetProjectItemFullPath(item);
        }
        
        return defaultPath;
    }
    public static string GetTemplatePlaceholderName(EnvDTE.ProjectItem item)
    {
        return String.Format("{0}.txt4", Path.GetFileNameWithoutExtension(item.Name));
    }
    
    public static EnvDTE.ProjectItem GetTemplateProjectItem(EnvDTE.DTE dte, OutputFile file, EnvDTE.ProjectItem defaultItem)
    {
        if (String.IsNullOrEmpty(file.ProjectName) == true && String.IsNullOrEmpty(file.FolderName) == true)
        {
            return defaultItem;
        }
        
        string templatePlaceholder = GetTemplatePlaceholderName(defaultItem);
        string itemPath = Path.GetDirectoryName(file.FileName); 
        string fullName = Path.Combine(itemPath, templatePlaceholder);
        EnvDTE.Project prj = null;
        EnvDTE.ProjectItem item = null;
        
        if (String.IsNullOrEmpty(file.ProjectName) == false)
        {
            prj = GetProject(dte, file.ProjectName);            
        }
        
        if (String.IsNullOrEmpty(file.FolderName) == true && prj != null)
        {
            return FindProjectItem(prj.ProjectItems, fullName, true);
        }
        else if (prj != null && String.IsNullOrEmpty(file.FolderName) == false)
        {
            item = GetAllProjectItemsRecursive(prj.ProjectItems).Where(i=>i.Name == file.FolderName).First();
        }
        else if (String.IsNullOrEmpty(file.FolderName) == false)
        {
            item = GetAllProjectItemsRecursive(
                dte.ActiveDocument.ProjectItem.ContainingProject.ProjectItems).
                Where(i=>i.Name == file.FolderName).First();
        }
        
        if (item != null)
        {
            return FindProjectItem(item.ProjectItems, fullName, true);
        }
        
        return defaultItem;
    }
    
    private static EnvDTE.ProjectItem FindProjectItem(EnvDTE.ProjectItems items, string fullName, bool canCreateIfNotExists)
    {
        EnvDTE.ProjectItem item = (from i in items.Cast<EnvDTE.ProjectItem>()
                                  where i.Name == Path.GetFileName(fullName)
                                  select i).FirstOrDefault();
        if (item == null)
        {
            File.CreateText(fullName);
            item = items.AddFromFile(fullName);
        }
        
        return item;
    }
    
    public static EnvDTE.Project GetProject(EnvDTE.DTE dte, string projectName)
    {
        return GetAllProjects(dte).Where(p=>p.Name == projectName).First();
    }
    
    public static IEnumerable<EnvDTE.Project> GetAllProjects(EnvDTE.DTE dte)
    {
        List<EnvDTE.Project> projectList = new List<EnvDTE.Project>();
        
        var folders = dte.Solution.Projects.Cast<EnvDTE.Project>().Where(p=>p.Kind == EnvDTE80.ProjectKinds.vsProjectKindSolutionFolder);

        foreach (EnvDTE.Project folder in folders)
        {
            if (folder.ProjectItems == null) continue;
            
            foreach (EnvDTE.ProjectItem item in folder.ProjectItems)
            {
                if (item.Object is EnvDTE.Project)
                    projectList.Add(item.Object as EnvDTE.Project);
            }
        }
        
        var projects = dte.Solution.Projects.Cast<EnvDTE.Project>().Where(p=>p.Kind != EnvDTE80.ProjectKinds.vsProjectKindSolutionFolder);

        if (projects.Count() > 0)
            projectList.AddRange(projects);
        
        return projectList;
    }
    
    public static EnvDTE.ProjectItem GetProjectItemWithName(EnvDTE.ProjectItems items, string itemName)
    {
        return GetAllProjectItemsRecursive(items).Cast<ProjectItem>().Where(i=>i.Name == itemName).First();
    }
    
    public static string GetProjectItemFullPath(EnvDTE.ProjectItem item)
    {
        if (item == null)
            return null;

        return item.Properties.Item("FullPath").Value.ToString();
    }
    
    public static IEnumerable<EnvDTE.ProjectItem> GetAllSolutionItems(EnvDTE.DTE dte)
    {
        List<EnvDTE.ProjectItem> itemList = new List<EnvDTE.ProjectItem>();

        foreach (Project item in GetAllProjects(dte))
        {
            if (item == null || item.ProjectItems == null) continue;
            
            itemList.AddRange(GetAllProjectItemsRecursive(item.ProjectItems));     
        }
        
        return itemList;
    }
    
    public static IEnumerable<EnvDTE.ProjectItem> GetAllProjectItemsRecursive(EnvDTE.ProjectItems projectItems) 
    {
        foreach (EnvDTE.ProjectItem projectItem in projectItems) 
        {
            if (projectItem.ProjectItems == null) continue;

            foreach (EnvDTE.ProjectItem subItem in GetAllProjectItemsRecursive(projectItem.ProjectItems))
            {
                yield return subItem;
            }
            
            
            yield return projectItem;
        }
    }
}

public sealed class OutputFile
{
    public OutputFile()
    {
        this.FileProperties = new FileProperties
        {
            CustomTool = String.Empty,
            BuildAction = BuildAction.None
        };
    }
    
    public string FileName { get; set; }
    public string ProjectName { get; set; }
    public string FolderName { get; set; }
    public string Content { get; set; }
    public FileProperties FileProperties { get; set; }
}

public class BuildAction
{
    public const string None = "None";
    public const string Compile = "Compile";
    public const string Content = "Content";
    public const string EmbeddedResource = "EmbeddedResource";
    public const string EntityDeploy = "EntityDeploy";
}

public sealed class FileProperties
{
    public FileProperties ()
    {
        this.TemplateParameter = new Dictionary<string,string>();    
    }
    
    public string CustomTool { get; set; }
    public string BuildAction { get; set; }
    public Dictionary<string, string> TemplateParameter { get; set; }
    
    internal string BuildActionString
    {
        get
        {
            return this.BuildAction;
        }
    }
}


#>

最後注意如果允許TT模板提示dll錯誤,那就根據錯誤提示引用相應的dll就可以了

 


在visio中畫實體聯系圖要使用哪個模板,急

喜gifts123355,
上像一個基本流程圖的選擇!這些都是後建的基本流程圖,相應的庫被加載,如果庫被加載就夠了!

希望能幫助你!

安順
 

mscoreedll在什位置

解決辦法:這是XP系統缺少有關文件,請到www.microsoft.com/...=17718下載安裝即可!

詳細介紹:

.NET Framework 是由 Microsoft 開發的一種全面且一致的編程模型,用於生成具有視覺震撼力的用戶體驗、無縫的安全通信和對一系列業務流程進行建模的能力的應用程序。

.NET Framework 4 將與舊的 Framework 版本並行工作。 默認情況下,基於早期版本的 Framework 的應用程序將繼續在目標版本上運行。

Microsoft .NET Framework 4 提供了以下新功能和改進:

公共語言運行時 (CLR) 和基類庫 (BCL) 的改進
性能改進,包括更好的多核心支持、後台垃圾回收和服務器上的探查器附加。
新的內存映射文件和數字類型。
更輕松的調試,包括轉儲調試、Watson 小型轉儲、64 位的混合模式調試和代碼協定。
有關 CLR 和 BCL 的增強功能的完整列表,請轉到此處。
Visual Basic 和 C# 語言中的創新,例如 lambda 語句、隱式行繼續符、動態調度和命名/可選參數。
數據訪問和建模的改進
利用 Entity Framework,開發人員可使用 .NET 對象和語言集成查詢 (LINQ) 對關系數據庫進行編程。 它具有多項新功能,包括持久性忽略和 POCO 支持、外鍵關聯、延遲加載、測試驅動開發支持、模型中的函數和新的 LINQ 運算符。 其他功能包括:帶自跟蹤實體的更好的 n 層支持、使用 T4 模板的可自定義的代碼生成、模型首次開發、改進的設計器體驗、更好的性能以及實體集的復數形式。 有關更多信息,請轉到此處。
WCF 數據服務是 .NET Framework 的一個組件,可以利用此服務創建基於 REST 的服務和應用程序,以便使用開放式數據協議 (OData) 在 Web 上公開和使用數據。 WCF 數據服務具有多項新功能,包括增強的 BLOB 支持、數據綁定、行計數、源自定義、投影和請求管道改進。 當前與 Microsoft Office 2010 的內置集成可將 Microsoft Office SharePoint Server 數據作為一個 OData 源公開,並使用 WCF 數據服務客戶端庫訪問該數據源。 有關更多信息,請轉到此處。
ASP.NET 的增強功能
對 HTML、元素 ID 和自定義 CSS 的更多控制,通過這些控制可更輕松地創建符合標准且 SEO 友好的 Web 窗體。
新的動態數據功能,包括新的查詢篩選器、實體模板、對 Entity Framework 4 的更豐富的支持以及可輕松應用於現有 Web 窗體的驗證和模板化功能。
針對新的 AJAX 庫改進的 Web 窗體支持,包括對內容傳遞網絡 (CDN) 的內置支持。
有關 ASP.NET 增強功能的完整列表,請轉到此處。
Windows Presentation Foundation (WPF) 的改進
添加對 Windows 7 多點觸控、功能區控件和任務欄擴展性功能的支持。
添加了對 Surface 2.0 SDK 的支持。
新的業務線控件,包括圖表控件、智能編輯、數據網格以及其他用於改......余下全文>>
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved