2010-12-09 15 views
17

Veritabanımın enumlarını oluşturmak için bir T4 şablonu oluşturmaya çalışıyorum. Temel olarak, SubSonic ile aynı özelliği istiyorum örn. Linq-to-SQL veya Varlık Framework için Product.Columns.ProductId 4.T4 şablonu Enumlar Oluşturulacak

Herhangi bir yardım çok takdir edilecektir. teşekkürler.

cevap

31

ben bir enum Seçtiğiniz bir arama tablosu dönüştürür benim ihtiyaçları için bir tane yazdım: bir EnumGenerator.ttinclude dosyası içinde bu kodu koyun:

<#@ template debug="true" hostSpecific="true" #> 
<#@ output extension=".generated.cs" #> 
<#@ Assembly Name="System.Data" #> 
<#@ import namespace="System.Data" #> 
<#@ import namespace="System.Data.SqlClient" #> 
<#@ import namespace="System.IO" #> 
<#@ import namespace="System.Text.RegularExpressions" #> 
<# 
    string tableName = Path.GetFileNameWithoutExtension(Host.TemplateFile); 
    string path = Path.GetDirectoryName(Host.TemplateFile); 
    string columnId = tableName + "ID"; 
    string columnName = "Name"; 
    string connectionString = "data source=.;initial catalog=DBName;integrated security=SSPI"; 
#> 
using System; 
using System.CodeDom.Compiler; 

namespace Services.<#= GetSubNamespace() #> 
{ 
    /// <summary> 
    /// <#= tableName #> auto generated enumeration 
    /// </summary> 
    [GeneratedCode("TextTemplatingFileGenerator", "10")] 
    public enum <#= tableName #> 
    { 
<# 
    SqlConnection conn = new SqlConnection(connectionString); 
    string command = string.Format("select {0}, {1} from {2} order by {0}", columnId, columnName, tableName); 
    SqlCommand comm = new SqlCommand(command, conn); 

    conn.Open(); 

    SqlDataReader reader = comm.ExecuteReader(); 
    bool loop = reader.Read(); 

    while(loop) 
    { 
#>  /// <summary> 
     /// <#= reader[columnName] #> configuration setting. 
     /// </summary> 
     <#= Pascalize(reader[columnName]) #> = <#= reader[columnId] #><# loop = reader.Read(); #><#= loop ? ",\r\n" : string.Empty #> 
<# 
    } 
#> } 
} 
<#+ 
    private string Pascalize(object value) 
    { 
     Regex rx = new Regex(@"(?:[^a-zA-Z0-9]*)(?<first>[a-zA-Z0-9])(?<reminder>[a-zA-Z0-9]*)(?:[^a-zA-Z0-9]*)"); 
     return rx.Replace(value.ToString(), m => m.Groups["first"].ToString().ToUpper() + m.Groups["reminder"].ToString().ToLower()); 
    } 

    private string GetSubNamespace() 
    { 
     Regex rx = new Regex(@"(?:.+Services\s)"); 
     string path = Path.GetDirectoryName(Host.TemplateFile); 
     return rx.Replace(path, string.Empty).Replace("\\", "."); 
    } 
#> 

Sonra bir istediğiniz bir zamanda enum oluşturulacak, sadece UserType.tt gibi veritabanı tablosu olarak aynı adı taşıyan bir tt dosyası oluşturun ve bu kodu koymak:

<#@ include file="..\..\T4 Templates\EnumGenerator.ttinclude" #> 

blog post numaralı telefonumdan daha da gelişmiş bir şablon hazırdır. Pascalize ait

+2

Bu kaygan. Bunu kendim yapmayı düşünüyordum, ama bana sıkıntıyı kurtardın. –

+2

@David Canlı: Teşekkürler. Bunu birkaç projede kullandım, bu yüzden başkalarıyla da paylaşmam gerektiğini düşündüm. –

+0

Pascalize { '9' .. '0', '' .. 'ile z', 'A' .. 'Z'} olmayan istenmeyen karakterleri kaldırmak gibi aralığı değil gibi '\' ya da '-' . Bu hat için bir düzeltme şansı var mı? –

2

Alternatif uygulama: Bir boş sonuçla sona Eğer

private static string Pascalize(object value) 
{ 
    if (value == null) 
     return null; 

    string result = value.ToString(); 

    if (string.IsNullOrWhiteSpace(result)) 
     return null; 

    result = new String(result.Select(ch => ((ch >= '0' && ch <= '9' || ch >= 'a' && ch <= 'z') ? ch : ((ch >= 'A' && ch <= 'Z') ? ((char)((int)ch + (int)'a' - (int)'A')) : '-'))).ToArray()); 
    string[] words = result.Split(new [] {'-'}, StringSplitOptions.RemoveEmptyEntries); 
    words = words.Select(w => ((w[0] >= 'a' && w[0] <= 'z') ? (w.Substring(0, 1).ToUpper() + w.Substring(1)) : w)).ToArray(); 
    result = words.Aggregate((st1, st2) => st1 + st2); 
    if (result[0] >= '0' && result[0] <= '9') 
     result = '_' + result; 

    return result; 
} 

, ben "Değerini" değeri olarak + id kullanılması önerilir.

Sonucu önceki değerlerine, size (kötü veri veya atlanmış karakter) oluşturuldu çiftleri varsa sonuna kadar '_' ekleyebilirsiniz karşılaştırılmalıdır.

E.g.

int value = Convert.ToInt32(reader[enumTable.ValueId]); 
string name = Pascalize(reader[enumTable.ValueName].ToString()); 
if (string.IsNullOrWhiteSpace(name)) 
    name = "Value" + value; 

while (result.Values.Where(v => v.Name == name).SingleOrDefault() != null) 
    name += '_'; 
İlgili konular