리플렉션을 통해 호출되는 메소드를 표시하는 가장 좋은 방법?


11

우리 소프트웨어에는 리플렉션을 통해 동적으로 찾아야하는 몇 가지 클래스가 있습니다. 클래스에는 모두 리플렉션 코드가 객체를 인스턴스화하는 특정 서명이있는 생성자가 있습니다.
그러나 누군가가 메서드가 참조되는지 (예 : Visual Studio Code Lens를 통해) 확인하면 리플렉션을 통한 참조는 계산되지 않습니다. 사람들은 자신의 참조를 그리워하고 명백하게 사용되지 않는 방법을 제거 (또는 변경) 할 수 있습니다.

리플렉션을 통해 호출되도록 의도 된 마크 / 문서 방법은 어떻게해야합니까?

이상적으로,이 방법은 동료와 Visual Studio / Roslyn 및 기타 자동화 된 도구가 방법이 리플렉션을 통해 호출되도록 의도 된 방식으로 표시되어야합니다.

우리가 사용할 수있는 두 가지 옵션을 알고 있지만 둘 다 만족스럽지 않습니다. Visual Studio에서 참조를 찾을 수 없으므로

  • 사용자 정의 속성을 사용 하고 생성자에이 속성을 표시하십시오.
    • 문제는 속성 속성이 메소드 참조가 될 수 없으므로 생성자가 여전히 0 참조를 갖는 것으로 표시한다는 것입니다.
    • 사용자 정의 속성에 익숙하지 않은 동료는이를 무시할 것입니다.
    • 현재 접근 방식의 장점은 리플렉션 부분이 속성을 사용하여 호출 해야하는 생성자를 찾을 수 있다는 것입니다.
  • 메소드 / 생성자가 리플렉션을 통해 호출되도록 문서화하려면 주석을 사용하십시오.
    • 자동화 된 도구는 주석을 무시합니다 (동료도 마찬가지 임).
    • XML 문서의 댓글은 비주얼 스튜디오 메소드 / 생성자에 추가 참조를 계산해야하는 데 사용할 수 있습니다
      하자 MyPlugin그의 생성자 반사를 통해 호출 할 수있는 클래스가. 호출 리플렉션 코드가 int매개 변수 를 취하는 생성자를 검색한다고 가정하십시오 . 다음 문서는 코드 렌즈가 참조자가 1 인 생성자를 보여줍니다.
      /// <see cref="MyPlugin.MyPlugin(int)"/> is invoked via reflection

어떤 더 나은 옵션이 있습니까?
리플렉션을 통해 호출되는 메소드 / 생성자를 표시하는 가장 좋은 방법은 무엇입니까?


분명히 말하면, 이것은 일종의 플러그인 시스템을위한 것입니다.
whatsisname

2
당신은 동료들이 당신이하는 모든 것을 무시하거나 그리워 할 것이라고 가정하고 있습니다. 문서화는 더 쉽고 깨끗하고 저렴하며 권장되는 방식으로 보입니다. 그렇지 않으면 선언적 프로그래밍이 존재하지 않을 것입니다.
Laiv

1
Resharper에는 [UsedImplictly] 속성이 있습니다.
코드 InChaos

4
Xml doc comment 옵션이 아마도 가장 좋은 옵션이라고 생각합니다. 짧고 자체 문서화되며 "해킹"이나 추가 정의가 필요하지 않습니다.
Doc Brown

2
XML 문서 주석에 대한 또 다른 투표. 어쨌든 문서를 작성하는 경우 생성 된 문서에서 두드러 져야합니다.
Frank Hileman

답변:


12

제안 된 솔루션의 조합 :

  • XML 문서 태그를 사용하여 생성자 / 메소드가 리플렉션을 통해 호출되었음을 문서화하십시오.
    이것은 동료 (및 미래의 자기 자신)에게 의도 된 사용법을 분명히해야합니다.
  • <see>생성자 / 메소드의 참조 횟수를 늘리려면 -tag를 통해 '트릭'을 사용하십시오 .
    이것은 코드 렌즈와 find 참조가 생성자 / 메소드가 참조되었음을 보여줍니다.
  • Resharper로 주석 달기 UsedImplicitlyAttribute
    • Resharper는 사실상의 표준이며 [UsedImplicitly]정확하게 의도 된 의미를 갖습니다.
    • Resharper를 사용하지 않는 사람들은 NuGet : PM>을 통해 JetBrains ReSharper Annotations 를 설치할 수 있습니다 .
      Install-Package JetBrains.Annotations
  • 전용 메소드이고 Visual Studio의 코드 분석을 사용 SupressMessageAttribute하는 경우 메시지에 사용 하십시오 CA1811: Avoid uncalled private code.

예를 들면 다음과 같습니다.

class MyPlugin
{
    /// <remarks>
    /// <see cref="MyPlugin.MyPlugin(int)"/> is called via reflection.
    /// </remarks>
    [JetBrains.Annotations.UsedImplicitly]
    public MyPlugin(int arg)
    {
        throw new NotImplementedException();
    }

    /// <remarks>
    /// <see cref="MyPlugin.MyPlugin(string)"/> is called via reflection.
    /// </remarks>
    [JetBrains.Annotations.UsedImplicitly]
    [System.Diagnostics.CodeAnalysis.SuppressMessage(
        "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode",
        Justification = "Constructor is called via reflection")]
    private MyPlugin(string arg)
    {
        throw new NotImplementedException();
    }
}

이 솔루션은 인간 독자와 C # 및 Visual Studio에서 가장 많이 사용되는 3 개의 정적 코드 분석 시스템 모두에 생성자를 의도적으로 사용합니다.
단점은 하나의 주석과 하나 또는 두 개의 주석이 약간 중복되어 보일 수 있다는 것입니다.


참고도있다 MeansImplicitUseAttribute이 자신의 특성을 확인하는 데 사용할 수있는 UsedImplicitly효과를. 이는 올바른 상황에서 많은 속성 노이즈를 줄일 수 있습니다.
Dave Cousineau

JetBrains에 대한 링크가 끊어졌습니다.
John Zabroski

5

.Net 프로젝트 에서이 문제가 없었지만 Java 프로젝트와 동일한 문제가 있습니다. 필자의 일반적인 접근 방식은 @SuppressWarnings("unused")주석 을 사용하여 이유를 설명 하는 주석을 추가하는 것입니다. 너무). 이는 정적 분석 도구가 코드에 직접적인 참조가 없어야한다는 것을 자동으로 인식하고 독자에게 자세한 이유를 제공한다는 이점이 있습니다.

Java와 동등한 C # @SuppressWarningsSuppressMessageAttribute입니다. 들어 개인 방법 당신은 메시지 사용할 수 있습니다 CA1811을 : 지껄 개인 코드를 피하십시오 ; 예 :

class MyPlugin
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage(
        "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode",
        Justification = "Constructor is called via reflection")]
    private MyPlugin(int arg)
    {
        throw new NotImplementedException();
    }
}

(모르지만 CLI는 내가 언급 한 Java와 유사한 속성을 지원한다고 가정합니다. 누군가가 그것이 무엇인지 알고 있다면 이에 대한 참조로 내 답변을 편집하십시오 ...)
Jules


1
나는 최근에 테스트를 수행하고 커버리지를 측정하는 것이 자바에서 실제로 사용되지 않는지를 알 수있는 좋은 방법이라는 것을 발견했다. 그런 다음 그것을 제거하거나 왜 사용하지 않는지 볼 수 있습니다 (반대가 예상되는 경우). 검색하는 동안 댓글에 더 많은 관심을 기울입니다.
Laiv

가 존재한다 SuppressMessageAttribute( msdn.microsoft.com/en-us/library/...을 ). 가장 가까운 메시지는 CA1811: Avoid uncalled private code( msdn.microsoft.com/en-us/library/ms182264.aspx )입니다. 아직 공개 코드에 대한 메시지를 찾지 못했습니다.
카스퍼 반 덴 버그

2

문서화의 대안은 리플렉션 호출이 성공적으로 실행되도록 유닛 테스트를하는 것입니다.

그렇게하면 누군가 빌드 / 테스트 프로세스가 메소드를 변경하거나 제거하면 무언가를 깨뜨렸다는 경고 메시지가 표시됩니다.


0

코드를 보지 않고도 상속을 도입하기에 좋은 장소가 될 것입니다. 이 클래스의 생성자가 호출 할 수있는 가상 또는 추상 메서드일까요? 표시하려는 메소드 인 경우 생성자 일뿐입니다. 실제로 메소드가 아닌 클래스를 표시하려고합니다. 과거에 클래스를 표시하기 위해 한 일은 빈 인터페이스를 만드는 것입니다. 그런 다음 코드 검사 도구 및 리팩토링은 인터페이스를 구현하는 클래스를 찾을 수 있습니다.


진정한 정상적으로 상속되는 길입니다. 그리고 클래스는 실제로 상속과 관련이 있습니다. 그러나 상속 이상의 새로운 인스턴스를 만듭니다. 또한 정적 메소드의 '상속'에 의존하며 C #은 클래스 슬롯을 지원하지 않기 때문에; 내가 사용하는 방법이 있지만이 의견의 범위를 벗어납니다.
카스퍼 반 덴 버그
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.