2012-06-29 2 views
0

컴파일 타임에 클래스에서 자동으로 C# 인터페이스를 생성 할 수있는 라이브러리가 있으면 궁금한데 t4 템플릿과 같은 것이 좋습니다. 컴파일 타임에 클래스에서 인터페이스를 생성하는 라이브러리를 찾으십시오.

최근, 내 자신의 시도를 만들었습니다,하지만 glitchy 그리고

당신이 TDD의 길을 갈 경우, 당신이 필요하기 때문에이 도구를 필요 (방법의 기본 매개 변수, 이벤트 등과 같은) 많은 특별한 경우를 지원하지 않습니다 많은 것들을위한 인터페이스를 많이 만들고 그러한 인터페이스의 구현은 단 하나 밖에 없다. (moq과 같은 도구를 사용하여 mock을 만든다고 가정)

조언을 구하십시오.

+0

내 경험이 TDD가 아닙니다. 당신은 단지 역할마다 하나의 인터페이스가 필요하고 일반적으로 제한된 수의 역할이 있습니다. – Gishu

+0

Gishu에 감사드립니다. 애플리케이션의 구성 요소는 대개 제한적입니다.) 그러나 앱 개발 프로세스를 진행할 때는 항상 인터페이스를 "조정"해야합니다. 더 많은 매개 변수와 메소드가 추가되었습니다. C# 인터페이스가 있고 구현되어있는 경우 두 가지를 모두 변경해야합니다. 코드 복제와 같은 방식으로 나를 찾고, 일을 더 단순하게 만들어주는 도구를 만들고 싶습니다. – IlliakaillI

+0

'인터페이스 플럭스'라는 문제가 생길 때마다 내 실수입니다. 내면을 디자인 할 때 인터페이스가 항상 바뀌는 것을 발견했습니다. 내가 처음으로 클라이언트를 디자인 할 때, 그렇지 않은 경우가 많습니다. 또한 Resharper는 인터페이스가 수정 될 때마다 신속하게 구현을 수정합니다. 하지만 네 상황은 너의 상황이야. – Gishu

답변

1

지식을 공유하기 위해 아래에서 내 버전을 게시 할 예정입니다.

"classesToFind"변수에서 인터페이스를 생성해야하는 구현을 정의합니다. 코드는 추한 것입니다. 언제든지 개선 사항을 게시 할 수있는 의견을 보내 드리겠습니다.

<#@ template language="C#" hostSpecific="true" debug="true" #> 
<#@ output extension=".cs" #> 

<#@ assembly name="System.Core.dll" #> 
<#@ assembly name="System.Xml.Linq.dll" #> 
<#@ assembly name="System.Xml.dll" #> 
<#@ assembly name="EnvDTE" #> 
<#@ assembly name="EnvDTE80" #> 

<#@ import namespace="EnvDTE" #> 
<#@ import namespace="EnvDTE80" #> 
<#@ Import Namespace="System.Collections" #> 
<#@ Import Namespace="System.Collections.Generic" #> 
<#@ import namespace="System.Linq" #> 
<#@ import namespace="System.Xml.Linq" #> 

namespace XXX.Engine.Interfaces { 

<# 
    Type transformationType = this.GetType(); 
    System.Reflection.PropertyInfo hostProperty = transformationType.GetProperty("Host"); 
    if (hostProperty == null) 
      throw new Exception("Unable to retrieve templating engine host. " 
        + "Ensure that the template includes hostspecific=\"True\" " 
        + "parameter in the \<#@ template \#> directive."); 

    Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost host = (Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost)hostProperty.GetValue(this, null); 
    IServiceProvider hostServiceProvider = (IServiceProvider)host; 
    EnvDTE.DTE dte = (EnvDTE.DTE)hostServiceProvider.GetService(typeof(EnvDTE.DTE)); 
    EnvDTE.ProjectItem containingProjectItem = dte.Solution.FindProjectItem(host.TemplateFile); 
    Project project = containingProjectItem.ContainingProject; 
    var elements = CodeElementsInProjectItems(project.ProjectItems); 
    var classesToFind = new[] { 
     "WebApplicationContext", 
     "Security", 
     "Emailer", 
     "Configuration", 
     "CacheContainer" 
    }; 
    var classes = elements.Where(el => el.Kind == vsCMElement.vsCMElementClass) 
          .Cast<CodeClass>() 
          .Where(cl => classesToFind.Contains(cl.Name)); 

    foreach(var codeClass in classes) 
    { 
#> 
     public partial interface I<#= codeClass.Name #> { 
<# 
      foreach(var member in codeClass.Members) { 
       var property = member as CodeProperty; 
       if(property != null) { 
#> 
        <#= property.Type.AsString #> <#= property.Name #> { <#= (property.Setter != null && property.Setter.Access == vsCMAccess.vsCMAccessPublic)?"set; ":string.Empty #><#= (property.Getter != null && property.Getter.Access == vsCMAccess.vsCMAccessPublic)?"get;":string.Empty #> } 
<# 
       } 
       var function = member as CodeFunction; 
       if(function != null) { 
        if(function.Access != vsCMAccess.vsCMAccessPublic) 
         continue; //skip not public members 
        if(function.Name == codeClass.Name) 
         continue; //skip constructor 
        string parms = ""; 
        var isFirstParam = true; 
        foreach (CodeParameter param in function.Parameters) { 
         parms += ((isFirstParam?"":", ") + param.Type.AsString + " " + param.Name); 
         isFirstParam = false; 
        } 
#>     <#= function.Type.AsString #> <#= function.Name #>(<#= parms #>); 
<# 
       } 
      } 
#> 
     } 
<# 
    } 
#> 
} 

<#+ 
public IEnumerable<CodeElement> CodeElementsInProjectItems(ProjectItems projectItems) { 
    foreach (ProjectItem projectItem in projectItems) { 
     foreach(CodeElement el in CodeElementsInProjectItem(projectItem)) { 
      yield return el; 
     } 
    } 
} 

public IEnumerable<CodeElement> CodeElementsInProjectItem(ProjectItem projectItem) { 
    FileCodeModel fileCodeModel = projectItem.FileCodeModel; 
    if (fileCodeModel != null) { 
     foreach (CodeElement codeElement in fileCodeModel.CodeElements) { 
      //WalkElements(codeElement, null); 
      foreach(CodeElement el in CodeElementDescendantsAndSelf(codeElement)) { 
       yield return el; 
      } 
     } 
    } 
    if (projectItem.ProjectItems != null) { 
     foreach (ProjectItem childItem in projectItem.ProjectItems) { 
      foreach (CodeElement el in CodeElementsInProjectItem(childItem)) { 
       yield return el; 
      } 
     } 
    }   
} 

public IEnumerable<CodeElement> CodeElementsDescendants(CodeElements codeElements) { 
    foreach(CodeElement element in codeElements) { 
     foreach (CodeElement descendant in CodeElementDescendantsAndSelf(element)) { 
      yield return descendant;     
     } 
    } 
} 

public IEnumerable<CodeElement> CodeElementDescendantsAndSelf(CodeElement codeElement) { 
    yield return codeElement; 

    CodeElements codeElements; 
    switch(codeElement.Kind) {   
     /* namespaces */ 
     case vsCMElement.vsCMElementNamespace: { 
      CodeNamespace codeNamespace = (CodeNamespace)codeElement;           
      codeElements = codeNamespace.Members; 
      foreach(CodeElement descendant in CodeElementsDescendants(codeElements)) 
      { 
       yield return descendant;     
      } 
      break; 
     } 
     /* Process classes */ 
     case vsCMElement.vsCMElementClass: {    
      CodeClass codeClass = (CodeClass)codeElement;    
      codeElements = codeClass.Members; 
      foreach(CodeElement descendant in CodeElementsDescendants(codeElements)) 
      {     
       yield return descendant;     
      }    
      break;  
     }   
    }  
} 
#> 
관련 문제