런타임에 프로그래밍 방식으로 요약 주석 가져오기
ASP.net 에서 메서드의 Xml-comments 요약 부분을 프로그래밍 방식으로 가져올 수 있는 방법을 찾고 있습니다.
이전 관련 게시물을 살펴보았는데 웹 환경에서 제공하는 방법이 없습니다.
타사 앱을 사용할 수 없고 웹 환경 때문에 Visual studio 플러그인도 사용할 수 없습니다.
제가 찾은 해결책 중 가장 가까운 것은 Jim Blackler 프로젝트이지만 DLL에서만 작동합니다.
당연히 'supply .CS file, get XML documentation'과 같은 것이 가장 좋습니다.
현재 상황
저는 웹 서비스를 가지고 있으며 동적으로 문서를 생성하려고 합니다.
메소드와 속성을 읽는 것은 쉽지만, 각 메소드에 대한 요약을 읽는 것은 저를 조금 힘들게 합니다.
/// <summary>
/// This Is what I'm trying to read
/// </summary>
public class SomeClass()
{
/// <summary>
/// This Is what I'm trying to read
/// </summary>
public void SomeMethod()
{
}
}
해결 방법 - 프로그램에 대한 성찰 사용.DLL/EXE를 프로그램과 함께 사용할 수 있습니다.XML 파일
Visual Studio에서 생성한 형제 .XML 파일을 보면 /members/members의 계층 구조가 상당히 평평하다는 것을 알 수 있습니다.MethodInfo 개체를 통해 DLL에서 각 메서드를 보유하기만 하면 됩니다.이 개체가 있으면 XML로 이동하고 XPATH를 사용하여 이 메서드에 대한 XML 문서가 포함된 멤버를 가져옵니다.
구성원 앞에는 문자가 붙습니다.메서드에 대한 XML 문서는 클래스에 대해 "M:" 앞에 "T:" 등이 나옵니다.
형제 XML 로드
string docuPath = dllPath.Substring(0, dllPath.LastIndexOf(".")) + ".XML";
if (File.Exists(docuPath))
{
_docuDoc = new XmlDocument();
_docuDoc.Load(docuPath);
}
이 xpath를 사용하여 메서드 XML 문서를 나타내는 멤버를 가져옵니다.
string path = "M:" + mi.DeclaringType.FullName + "." + mi.Name;
XmlNode xmlDocuOfMethod = _docuDoc.SelectSingleNode(
"//member[starts-with(@name, '" + path + "')]");
이제 "//"의 모든 행에 대해 자식 노드를 스캔합니다. 때때로 // 요약에 빈칸이 추가될 수 있습니다. 문제가 발생하면 이를 사용하여 제거하십시오.
var cleanStr = Regex.Replace(row.InnerXml, @"\s+", " ");
XML 요약은 .NET 어셈블리에 저장되지 않습니다. Visual Studio를 사용하는 경우 빌드의 일부로 XML 파일에 선택적으로 기록됩니다.
따라서 컴파일된 .NET 어셈블리(.EXE 또는 .DLL)에 대한 반영을 통해 각 방법의 XML 요약을 "꺼낼" 방법이 없습니다. 데이터가 단순히 꺼낼 수 없기 때문입니다.데이터를 사용하려면 빌드 프로세스의 일부로 XML 파일을 출력하도록 빌드 환경에 지시하고 런타임에 XML 파일을 구문 분석하여 요약 정보를 얻어야 합니다.
은 다을사문방 '서화할을 '다음니 '를 수 .System.ComponentModel.DataAnnotations.DisplayAttribute
예:
[Display(Name = "Foo", Description = "Blah")]
void Foo()
{
}
그런 다음 반사를 사용하여 런타임에 설명을 끌어옵니다.
@Oleksandr가 만든 삭제된 게시물Ieremenko, 이 스레드는 제 솔루션의 기초가 된 이 기사 https://jimblackler.net/blog/ ?p=49에 링크되어 있습니다.
아래는 Jim Blackler의 코드를 수정하여 MemberInfo 및 Type 객체에서 확장 메서드를 만들고 사용할 수 없는 경우 요약 텍스트 또는 빈 문자열을 반환하는 코드를 추가한 것입니다.
사용.
var typeSummary = typeof([Type Name]).GetSummary();
var methodSummary = typeof([Type Name]).GetMethod("[Method Name]").GetSummary();
확장 클래스
/// <summary>
/// Utility class to provide documentation for various types where available with the assembly
/// </summary>
public static class DocumentationExtensions
{
/// <summary>
/// Provides the documentation comments for a specific method
/// </summary>
/// <param name="methodInfo">The MethodInfo (reflection data ) of the member to find documentation for</param>
/// <returns>The XML fragment describing the method</returns>
public static XmlElement GetDocumentation(this MethodInfo methodInfo)
{
// Calculate the parameter string as this is in the member name in the XML
var parametersString = "";
foreach (var parameterInfo in methodInfo.GetParameters())
{
if (parametersString.Length > 0)
{
parametersString += ",";
}
parametersString += parameterInfo.ParameterType.FullName;
}
//AL: 15.04.2008 ==> BUG-FIX remove “()” if parametersString is empty
if (parametersString.Length > 0)
return XmlFromName(methodInfo.DeclaringType, 'M', methodInfo.Name + "(" + parametersString + ")");
else
return XmlFromName(methodInfo.DeclaringType, 'M', methodInfo.Name);
}
/// <summary>
/// Provides the documentation comments for a specific member
/// </summary>
/// <param name="memberInfo">The MemberInfo (reflection data) or the member to find documentation for</param>
/// <returns>The XML fragment describing the member</returns>
public static XmlElement GetDocumentation(this MemberInfo memberInfo)
{
// First character [0] of member type is prefix character in the name in the XML
return XmlFromName(memberInfo.DeclaringType, memberInfo.MemberType.ToString()[0], memberInfo.Name);
}
/// <summary>
/// Returns the Xml documenation summary comment for this member
/// </summary>
/// <param name="memberInfo"></param>
/// <returns></returns>
public static string GetSummary(this MemberInfo memberInfo)
{
var element = memberInfo.GetDocumentation();
var summaryElm = element?.SelectSingleNode("summary");
if (summaryElm == null) return "";
return summaryElm.InnerText.Trim();
}
/// <summary>
/// Provides the documentation comments for a specific type
/// </summary>
/// <param name="type">Type to find the documentation for</param>
/// <returns>The XML fragment that describes the type</returns>
public static XmlElement GetDocumentation(this Type type)
{
// Prefix in type names is T
return XmlFromName(type, 'T', "");
}
/// <summary>
/// Gets the summary portion of a type's documenation or returns an empty string if not available
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public static string GetSummary(this Type type)
{
var element = type.GetDocumentation();
var summaryElm = element?.SelectSingleNode("summary");
if (summaryElm == null) return "";
return summaryElm.InnerText.Trim();
}
/// <summary>
/// Obtains the XML Element that describes a reflection element by searching the
/// members for a member that has a name that describes the element.
/// </summary>
/// <param name="type">The type or parent type, used to fetch the assembly</param>
/// <param name="prefix">The prefix as seen in the name attribute in the documentation XML</param>
/// <param name="name">Where relevant, the full name qualifier for the element</param>
/// <returns>The member that has a name that describes the specified reflection element</returns>
private static XmlElement XmlFromName(this Type type, char prefix, string name)
{
string fullName;
if (string.IsNullOrEmpty(name))
fullName = prefix + ":" + type.FullName;
else
fullName = prefix + ":" + type.FullName + "." + name;
var xmlDocument = XmlFromAssembly(type.Assembly);
var matchedElement = xmlDocument["doc"]["members"].SelectSingleNode("member[@name='" + fullName + "']") as XmlElement;
return matchedElement;
}
/// <summary>
/// A cache used to remember Xml documentation for assemblies
/// </summary>
private static readonly Dictionary<Assembly, XmlDocument> Cache = new Dictionary<Assembly, XmlDocument>();
/// <summary>
/// A cache used to store failure exceptions for assembly lookups
/// </summary>
private static readonly Dictionary<Assembly, Exception> FailCache = new Dictionary<Assembly, Exception>();
/// <summary>
/// Obtains the documentation file for the specified assembly
/// </summary>
/// <param name="assembly">The assembly to find the XML document for</param>
/// <returns>The XML document</returns>
/// <remarks>This version uses a cache to preserve the assemblies, so that
/// the XML file is not loaded and parsed on every single lookup</remarks>
public static XmlDocument XmlFromAssembly(this Assembly assembly)
{
if (FailCache.ContainsKey(assembly))
{
throw FailCache[assembly];
}
try
{
if (!Cache.ContainsKey(assembly))
{
// load the docuemnt into the cache
Cache[assembly] = XmlFromAssemblyNonCached(assembly);
}
return Cache[assembly];
}
catch (Exception exception)
{
FailCache[assembly] = exception;
throw;
}
}
/// <summary>
/// Loads and parses the documentation file for the specified assembly
/// </summary>
/// <param name="assembly">The assembly to find the XML document for</param>
/// <returns>The XML document</returns>
private static XmlDocument XmlFromAssemblyNonCached(Assembly assembly)
{
var assemblyFilename = assembly.Location;
if (!string.IsNullOrEmpty(assemblyFilename))
{
StreamReader streamReader;
try
{
streamReader = new StreamReader(Path.ChangeExtension(assemblyFilename, ".xml"));
}
catch (FileNotFoundException exception)
{
throw new Exception("XML documentation not present (make sure it is turned on in project properties when building)", exception);
}
var xmlDocument = new XmlDocument();
xmlDocument.Load(streamReader);
return xmlDocument;
}
else
{
throw new Exception("Could not ascertain assembly filename", null);
}
}
}
나모션으로 하시면 됩니다.다음 정보를 얻기 위한 Reflection NuGet 패키지:
string summary = typeof(Foo).GetXmlDocsSummary();
https://github.com/NSwag/NSwag - nuget NSwag 소스를 볼 수 있습니다.코드 생성 - 요약, 사용법도 가져옵니다.
var generator = new WebApiAssemblyToSwaggerGenerator(settings);<br/>
var swaggerService = generator.GenerateForController("namespace.someController");<br/>
// string with comments <br/>
var swaggerJson = swaggerService.ToJson();
(dll에 대해 ILSPY 디컴파일러를 사용해보고 코드와 주석을 확인합니다.)
만약 당신이 코멘트를 얻으려는 소스 코드에 접근할 수 있다면, 당신은 Roslin 컴파일러 플랫폼을 사용하여 그것을 할 수 있습니다.기본적으로 모든 중간 컴파일러 메타데이터에 액세스할 수 있으며 원하는 모든 작업을 수행할 수 있습니다.
다른 사람들이 제안하는 것보다 조금 더 복잡하지만, 당신의 요구가 무엇인지에 따라 선택사항이 될 수도 있습니다.
이 게시물에는 비슷한 것에 대한 코드 샘플이 있는 것 같습니다.
언급URL : https://stackoverflow.com/questions/15602606/programmatically-get-summary-comments-at-runtime
'programing' 카테고리의 다른 글
SQL Server에서 증분 ID의 시작 값을 재설정하는 방법 (0) | 2023.06.28 |
---|---|
Xcode에서 메서드 참조 찾기 (0) | 2023.06.28 |
CreateObject("Excel") 간의 차이입니다.애플리케이션").문제집.워크북을 열고 작업장만 엽니다.열다. (0) | 2023.06.28 |
jQuery를 사용하여 ASP.NET 웹 서비스를 호출하는 방법은 무엇입니까? (0) | 2023.06.28 |
이동 평균 계산 (0) | 2023.06.28 |