문제

몇 가지 특별한 방법이 있으며 컴파일 된 어셈블리에서 호출을 분석하고 싶습니다.

예시:

public static class SrcHelper {
    [MySpecialMethod]
    [Conditional( "DEBUG" )]
    public static void ToDo( params object[] info ) {
        /* do nothing */
        /* this method is not called when code is compiled in RELEASE mode */
    }
}
// ... somewhere else in another assembly ...
Array CreateArraySampleMethod( int size ) {
    // This call has only informative character. No functionality is required.
    SrcHelper.ToDo( "Should create array of ", typeof( MyClass ), " with specified size." );
    throw new NotImplementedException();
}

이 컴파일 된 코드에서 나는 인수 값을 얻고 싶습니다 { "MyClass의 배열을 만들어야합니다." }. 모노에서 Cecil을 사용하려고 시도했으며 "Todo"방법에 대한 지침을 찾았습니다. 그러나 이제 나는 인수 값으로 지시를 식별하는 방법을 혼동하고 있습니다.

복잡한 상황이있을 수 있으며 일부 논쟁의 가치는 해결 될 수 없습니다. 그러나 나는 일정한 값 만 해결해야한다. 내 목적으로 충분하다.

감사.

편집하다:"TODO"방법 (및 유사한 방법)은 주석 (// * ... * /)의 대안으로 사용되어야하며, 편집 후 콘크리트 어셈블리에 대한 설명 및자가 생성 문서 및 TODO 목록이어야합니다.

도움이 되었습니까?

해결책

코드 생성은 다소 혼란 스럽지만 간단한 경우에는 수행 할 수 있습니다.

컴파일 :

public static void Main(string[] args)
{
    Console.WriteLine("", // ignore this argument
       "Should create array of ", typeof(int), " with specified size." "x");
}

(Params Overload를 사용하도록 강제로 "x"추가)

주어진

.method public hidebysig static void Main(string[] args) cil managed
{
    .custom instance void [mscorlib]System.STAThreadAttribute::.ctor()
    .maxstack 4
    .locals init (
        [0] object[] objArray)
    L_0000: ldstr ""
    L_0005: ldc.i4.4 
    L_0006: newarr object
    L_000b: stloc.0 
    L_000c: ldloc.0 
    L_000d: ldc.i4.0 
    L_000e: ldstr "Should create array of "
    L_0013: stelem.ref 
    L_0014: ldloc.0 
    L_0015: ldc.i4.1 
    L_0016: ldtoken int32
    L_001b: call class [mscorlib]System.Type 
                [mscorlib]System.Type::GetTypeFromHandle(
                    valuetype [mscorlib]System.RuntimeTypeHandle)
    L_0020: stelem.ref 
    L_0021: ldloc.0 
    L_0022: ldc.i4.2 
    L_0023: ldstr " with specified size."
    L_0028: stelem.ref 
    L_0029: ldloc.0 
    L_002a: ldc.i4.3 
    L_002b: ldstr "x"
    L_0030: stelem.ref 
    L_0031: ldloc.0 
    L_0032: call void [mscorlib]System.Console::WriteLine(string, object[])
    L_0037: ret 
}

따라서 IL을 구문 분석하여 컴파일러 생성 어레이로 푸시되는 인수를 감지하는 것입니다. 연약하지만 말하기에 충분할 수있는 유전 주의자 :

  1. '내 방법'에 대한 호출을 찾으십시오.
  2. 가장 가까운 이전 Newarr 객체를 찾으십시오
  3. 이들 사이에 모든 ldstr과 ldtoken을 가져 가서 그들이 논쟁이라고 가정하십시오.

이것은 거칠지 만 필요에 충분할 수 있습니다.

AOP 스타일의 접근 방식은 당신이 원하는 것을 얻을 수 있습니다 실행 시간 단순히 모든 호출을 값을 덤프하기 위해 간단히 계측하면 SOMPILE 시대에 위의 접근 방식은 IL 만 주어진 유일한 현실적인 옵션입니다.

생성 된 코드는 릴리스 빌드에서 매우 다를 수 있으며, 자동 생성 배열 구절을 명시 적으로 생성 한 배열 구절 (통화 사이트에서 또는 다른 메소드/생성자/클래스에서 더 멀리있을 수 있습니다.

단서

편집 한 후에이 작업을 수행하려는 이유에 대해서는 속성 기반 주석이 훨씬 더 나은 솔루션이라는 점에 주목해야합니다. 직접 귀속 할 수있는 방법에서 왜이 작업을 수행하고 싶은지 알 수 없습니다 ...

다른 팁

무슨 말인지 잘 모르겠습니다. 그러나 당신의 기능은 실제로 만 얻는다는 것을 주목하십시오 하나 인수 : 배열. 그것이 당신이 일리노이에서 얻는 것입니다. 내부에 함수, 배열을 걸어 가서 그 값을 얻을 수 있습니다.

public static void ToDo( params object[] info ) {
    foreach (object x in info)
        Console.WriteLine(x);
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top