성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] How can I tell whether two programs...
[정성태] The case of the fail-fast crashes c...
[정성태] Creating Docker multi-arch images f...
[정성태] BinaryFormatter removed from .NET 9...
[정성태] Extending the Windows Shell Progres...
[우광현] 와..... 범위를 잡았으니 클라이언트가 해당 범위를 확인해본다...
[정성태] 딱히, 그것 이상으로 더 설명할 내용이 없습니다. 동적 포...
[정성태] If Windows 3.11 required a 32-bit p...
[정성태] What is a hard error, and what make...
[괴물신인] 질문작성자인데 이 글을 이제봤네요 ㄷㄷ 이 글처럼 타입별로 인...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>C# - Source Generator를 적용한 XmlCodeGenerator</h1> <p> Source Generator를 사용하면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C# - Source Generator 소개 ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12223'>https://www.sysnet.pe.kr/2/0/12223</a> </pre> <br /> 예전에 만들어 둔 XmlCodeGenerator를,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Visual Studio 확장으로 XmlCodeGenerator 제작하는 방법 ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/1518'>https://www.sysnet.pe.kr/2/0/1518</a> Visual Studio Gallery - XmlCodeGenerator ; <a target='tab' href='http://visualstudiogallery.msdn.microsoft.com/20163975-c675-4f1c-986f-d2489136469d'>http://visualstudiogallery.msdn.microsoft.com/20163975-c675-4f1c-986f-d2489136469d</a> </pre> <br /> Visual Studio 도구가 아닌, 프로젝트 내에서의 참조로 해결할 수 있습니다. 하는 김에 지금 업데이트를 해볼까요? ^^ 간단하게 기존 XmlCodeGenerator 솔루션에,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > stjeong / XmlCodeGenerator ; <a target='tab' href='https://github.com/stjeong/XmlCodeGenerator'>https://github.com/stjeong/XmlCodeGenerator</a> </pre> <br /> .NET Standard Library 유형의 XmlSrcGenerator 프로젝트를 추가하고, ISourceGenerator로서 동작하기 위한 패키지 참조를 한 후,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Install-Package Microsoft.CodeAnalysis.Analyzers -Version 3.0.0 Install-Package Microsoft.CodeAnalysis.CSharp.Workspaces -Version 3.6.0 </pre> <br /> 기존의 XML + XSLT 처리를 담당하는 코드를 추가만 하면 끝입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > <span style='color: blue; font-weight: bold'>[Generator] public class SourceCodeGenerator : ISourceGenerator</span> { static Dictionary<string, XslCompiledTransform> xsltDict = new Dictionary<string, XslCompiledTransform>(); internal const string DefaultXslFileName = "default.xslt"; <span style='color: blue; font-weight: bold'>public void Execute(SourceGeneratorContext context)</span> { string fileNamespace = context.Compilation.GlobalNamespace.GetNamespaceMembers().First().ToDisplayString(); foreach (AdditionalText item in context.AdditionalFiles) { if (item.Path.EndsWith(".xml", StringComparison.OrdinalIgnoreCase) == false) { continue; } string baseFolder = Path.GetDirectoryName(item.Path); string txt = GenerateCode(item.Path, fileNamespace, baseFolder); string fileName = Path.GetFileNameWithoutExtension(item.Path) + ".partial.xml"; context.AddSource(fileName, SourceText.From(txt, Encoding.UTF8)); } } // ...[생략].... } </pre> <br /> <hr style='width: 50%' /><br /> <br /> 일단, 저런 식으로 개발된 Source Generator를 사용하는 측에서 보면, 참조 후에 수작업으로 다음의 항목을 csproj에 추가해야 하는데 다소 불편한 점이 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > <ItemGroup> <ProjectReference Include="..\XmlSrcGenerator\XmlSrcGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" /> </ItemGroup> </pre> <br /> 이러한 불편을 덜어줄 수 있는 것이 바로 "Analyzer"로서 NuGet에 등록하는 것입니다. 실제로 제가 다음의 NuGet repo에 XmlSrcGenerator를 등록해 두었으니,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > XmlSrcGenerator ; <a target='tab' href='https://www.nuget.org/packages/XmlSrcGenerator/'>https://www.nuget.org/packages/XmlSrcGenerator/</a> </pre> <br /> 사용하는 측에서는 해당 패키지를 참조하고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Install-Package XmlSrcGenerator -Version 1.0.5 </pre> <br /> XML과 XSLT 파일을 추가한 후 다음과 같이 XML 파일에 대해 Build Action을 "C# analyzer additional file"로 설정해 주면,<br /> <br /> <img alt='xml_code_gen_1.png' src='/SysWebRes/bbs/xml_code_gen_1.png' /><br /> <br /> 컴파일 시에, XML + XSLT로 출력된 소스 코드를 포함시켜 빌드를 완성하게 됩니다. (<a target='tab' href='https://www.sysnet.pe.kr/bbs/DownloadAttachment.aspx?fid=1593&boardid=331301885'>첨부 파일은 위의 예제 프로젝트를 포함</a>합니다.)<br /> <br /> <hr style='width: 50%' /><br /> <br /> 참고로, Build Action을 "C# analyzer additional file"로 설정해 주면, SourceGeneratorContext의 AdditionalFiles로 열람할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > using Microsoft.CodeAnalysis; using System; namespace XmlCodeGenerator { public class SourceCodeGenerator : ISourceGenerator { public void Execute(SourceGeneratorContext context) { foreach (AdditionalText item in context.AdditionalFiles) { // "C# analyzer additional file"로 설정된 파일 열거 } } public void Initialize(InitializationContext context) { } } } </pre> <br /> <hr style='width: 50%' /><br /> <br /> 그나저나, XmlCodeGenerator처럼 Visual Studio의 확장으로 개발하는 것이 좋을까요? XmlSrcGenerator처럼 Analyzer로서 개발하는 것이 좋을까요? 사실, 도구로서 개발하는 것은 너무 불편합니다. VS Extension을 개발해 보신 분들이라면, 참조한 어셈블리 중 Microsoft.VisualStudio.Shell.<span style='color: blue; font-weight: bold'>11.0</span>, Microsoft.VisualStudio.Shell.Interop.<span style='color: blue; font-weight: bold'>8.0</span> 등에서의 버전 번호가 아주 지긋지긋하게 느껴졌을 것입니다. ^^ 이러한 VS.NET IDE의 버전 의존성이 Analyzer로서 개발하면 없어진다는 것 자체가 장점입니다. <br /> <br /> 게다가, 소스 코드 생성을 하려면 VS.NET IDE 내에서만 가능하다는 것도 도구로 개발했을 때의 단점입니다. Analyzer로서 동작하면 Visual Studio Code뿐만 아니라 명령행 빌드에서까지 자유롭게 소스 코드 생성을 할 수 있으므로 범용성이 향상됩니다.<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
2962
(왼쪽의 숫자를 입력해야 합니다.)