2010-07-21 16 views
12

मैं एक टी 4 स्क्रिप्ट लिख रहा हूं जो कुछ वर्गों पर प्रतिबिंबित करता है और उनके आधार पर कोड जनरेशन प्रदान करता है। समस्या यह है कि मेरी स्क्रिप्ट त्रुटिपूर्ण है, कह रही है कि मेरे वर्तमान प्रोजेक्ट में कक्षाओं तक पहुंचा नहीं जा सकता है।टी 4 टूलबॉक्स - वर्तमान विधानसभा में कक्षा का संदर्भ

स्क्रिप्ट स्वयं उसी वर्ग में रहता है जैसे कक्षाएं मैं संदर्भित करने की कोशिश कर रहा हूं। मैंने नेमस्पेस, फ़ाइल का संदर्भ देने और वर्तमान असेंबली (प्रोजेक्ट स्वयं) के संदर्भ को जोड़ने का प्रयास किया है - सभी को कोई फायदा नहीं हुआ।

मुझे क्या याद आ रही है?

उत्तर

9

मुझे विश्वास है कि यह निको और यूओएस की तलाश में है। टी 4 टेम्पलेट्स के साथ परियोजना के नाम पर बस "MyAssembly.CodeGeneration" को बदलें। ध्यान में रखने की

<#@ assembly name="$(TargetPath)MyAssembly.dll" #> 
<#@ import namespace="MyAssembly.CodeGeneration" #> 
+8

मैंने इसके बजाय $ (TargetPath) का उपयोग किया। यह डीएलएल के लिए मैक्रो है। <# @ असेंबली नाम = "$ (लक्ष्यपैथ)" #> <# @ आयात नामस्थान = "MyAssembly.CodeGeneration" #> –

+0

यदि आप मूल समाधान भी छोड़ देते हैं तो यह अच्छा होगा –

2

एक बात है कि टी -4 स्क्रिप्ट आप लिख रहे हैं वास्तव में नहीं है "एक ही विधानसभा में रहते हैं" है - क्योंकि यह डिजाइन समय कोड है, रन-टाइम कोड नहीं। दूसरे शब्दों में - यह आपके असेंबली में सभी पर संकलित नहीं होता है।

इसके बजाए, जब आप कोड लिख रहे हों तो टी 4 टेम्पलेट स्क्रिप्ट चलती है - या, यदि आपके पास कुछ प्रोग्राम हैं, तो जब भी आप अपने प्रोग्राम को बनाते/संकलित करते हैं। क्योंकि यह वास्तव में आपके प्रोजेक्ट, कोड से अलग है, हालांकि, इसमें आपके प्रोजेक्ट की असेंबली को सीधे संदर्भित करने की कोई क्षमता नहीं है - जब तक कि आप DTE जैसे कुछ उपयोग न करें - जो आपको विजुअल स्टूडियो पर्यावरण को स्वयं एक्सेस करने और तत्वों का पता लगाने की क्षमता देता है जैसे वर्तमान में लोड की गई परियोजना।

<#@ template language="C#" debug="false" hostspecific="true" #> 
<#@ output extension=".js" #> 
<#@ assembly name="System" #> 
<#@ assembly name="System.Core" #> 
<#@ assembly name="System.Data.Entity" #> 
<#@ assembly name="EnvDTE" #> 
<#@ import namespace="EnvDTE" #> 
<#@ include file="T4Toolbox.tt" #> 
<#@ import namespace="System" #> 
<#@ import namespace="System.Collections" #> 
<#@ import namespace="System.Collections.Generic" #> 
<#@ import namespace="System.Linq" #> 
<#@ import namespace="System.Reflection" #> 

string targetNamespace = "MyNamespace"; 
var dte = (DTE)TransformationContext.Current.GetService(typeof(DTE)); 
var project = dte.Solution.FindProjectItem(TransformationContext.Current.Host.TemplateFile).ContainingProject); 

var classes = FindClasses(project, targetNamespace, ""); 

<# foreach (CodeClass c in classes) { #> 

    public class <#= c.Name #> { 

<#  var properties = c.Members.OfType<EnvDTE.CodeProperty>() 
      .Where(p => p.Access.HasFlag(vsCMAccess.vsCMAccessPublic)) 
      .OrderBy(p => p.Name); 
     foreach (var prop in properties) { 
#> 

     public <#= prop.Type.AsString #> <#= prop.Name #> { get; set; } 

<#  } #> 

    } 

<# } #> 

<#+ List<CodeClass> FindClasses(Project project, string ns, string className) { 
     List<CodeClass> result = new List<CodeClass>(); 
     FindClasses(project.CodeModel.CodeElements, className, ns, result, false); 
     return result; 
    } 
    void FindClasses(CodeElements elements, string className, string searchNamespace, List<CodeClass> result, bool isNamespaceOk) { 
     if (elements == null) return; 
     foreach (CodeElement element in elements) { 
      if (element is CodeNamespace) { 
       CodeNamespace ns = element as CodeNamespace; 
       if (ns != null) { 
        if (ns.FullName == searchNamespace) 
         FindClasses(ns.Members, className, searchNamespace, result, true); 
        else 
         FindClasses(ns.Members, className, searchNamespace, result, false); 
       } 
      } else if (element is CodeClass && isNamespaceOk) { 
       CodeClass c = element as CodeClass; 
       if (c != null) { 
        if (c.FullName.Contains(className)) 
         result.Add(c); 

        FindClasses(c.Members, className, searchNamespace, result, true); 
       } 
      } 
     } 
    } 

यह स्क्रिप्ट, संक्षेप में, एक विशिष्ट नाम स्थान के माध्यम से (इस मामले "MyNamespace" में), कक्षाओं के सभी के माध्यम से उसमें चलेंगे पुनरावृति, तो उत्पादन एक:

उदाहरण के लिए, निम्न स्क्रिप्ट पर विचार नई कोड फ़ाइल जो केवल getter/setter के साथ अपने सार्वजनिक गुणों को सूचीबद्ध करती है - संक्षेप में, वस्तुओं के एक पॉको का उत्पादन। मेरी कुछ परियोजनाओं में, मैं अपने पीओसीओ के आधार पर जावास्क्रिप्ट ऑब्जेक्ट्स जेनरेट करने के लिए इस कोड के एक अनुकूलित संस्करण का उपयोग करता हूं, ताकि मेरे जेएस मॉडल हमेशा एक सर्वरियलिटी परिप्रेक्ष्य से मेरे सर्वर-साइड ऑब्जेक्ट्स के साथ सिंक हो सकें।

इसे करने के लिए चाल है, हालांकि, पहली कुछ पंक्तियों में है:

var dte = (DTE)TransformationContext.Current.GetService(typeof(DTE)); 
var project = dte.Solution.FindProjectItem(TransformationContext.Current.Host.TemplateFile).ContainingProject); 
var classes = FindClasses(project, targetNamespace, ""); 

संक्षेप में, DTE सेवा दृश्य स्टूडियो पूछ रहा है यह वर्तमान में-लोडेड Solution के एक अमूर्त मॉडल देने के लिए और यह Projects है । इसके बाद हम Project लोड करते हैं जिसमें वर्तमान TemplateFile संग्रहीत किया जाता है, और FindClasses() विधि में, उस प्रोजेक्ट के भीतर कक्षाओं को पार्स करें जो हमारे खोज मानदंड से मेल खाते हैं।

मैं उदाहरण के कोड आप से कूद करने के लिए एक प्रारंभिक बिंदु देता है आशा है कि - लेकिन अगर आप अधिक विस्तार की जरूरत है, यहाँ कुछ अतिरिक्त संदर्भ आप में अपने दाँत सिंक करने के लिए कर रहे हैं:

0

संदर्भ में यह आम तरीका है।फिर जांचें कि असेंबली लोड हो गई है, यदि नहीं - स्टब कोड उत्पन्न करें (संकलन संभव बनाने के लिए; संकलन के बाद फिर से टी 4 चलाएं, वास्तविक कोड को जेनरेट करने के लिए)। और यूनिट टेस्ट है जो स्टब कोड को उत्पादन में जा सकता है।

0

किसी कारण से मुझे @brian समाधान काम नहीं मिल सका। मैं यह कर रहा हूं मेरे मामले में टी 4 जेनरेटर एक ही समाधान में मेरी अलग परियोजना थी।

<#@ assembly name="$(SolutionDir)\T4Generators\bin\Debug\T4Generators.dll" #> 
<#@ import Namespace="T4Generators" #> 
संबंधित मुद्दे