지식을 공유하기 위해 아래에서 내 버전을 게시 할 예정입니다.
"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;
}
}
}
#>
내 경험이 TDD가 아닙니다. 당신은 단지 역할마다 하나의 인터페이스가 필요하고 일반적으로 제한된 수의 역할이 있습니다. – Gishu
Gishu에 감사드립니다. 애플리케이션의 구성 요소는 대개 제한적입니다.) 그러나 앱 개발 프로세스를 진행할 때는 항상 인터페이스를 "조정"해야합니다. 더 많은 매개 변수와 메소드가 추가되었습니다. C# 인터페이스가 있고 구현되어있는 경우 두 가지를 모두 변경해야합니다. 코드 복제와 같은 방식으로 나를 찾고, 일을 더 단순하게 만들어주는 도구를 만들고 싶습니다. – IlliakaillI
'인터페이스 플럭스'라는 문제가 생길 때마다 내 실수입니다. 내면을 디자인 할 때 인터페이스가 항상 바뀌는 것을 발견했습니다. 내가 처음으로 클라이언트를 디자인 할 때, 그렇지 않은 경우가 많습니다. 또한 Resharper는 인터페이스가 수정 될 때마다 신속하게 구현을 수정합니다. 하지만 네 상황은 너의 상황이야. – Gishu