문제
몇 가지 특별한 방법이 있으며 컴파일 된 어셈블리에서 호출을 분석하고 싶습니다.
예시:
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을 구문 분석하여 컴파일러 생성 어레이로 푸시되는 인수를 감지하는 것입니다. 연약하지만 말하기에 충분할 수있는 유전 주의자 :
- '내 방법'에 대한 호출을 찾으십시오.
- 가장 가까운 이전 Newarr 객체를 찾으십시오
- 이들 사이에 모든 ldstr과 ldtoken을 가져 가서 그들이 논쟁이라고 가정하십시오.
이것은 거칠지 만 필요에 충분할 수 있습니다.
AOP 스타일의 접근 방식은 당신이 원하는 것을 얻을 수 있습니다 실행 시간 단순히 모든 호출을 값을 덤프하기 위해 간단히 계측하면 SOMPILE 시대에 위의 접근 방식은 IL 만 주어진 유일한 현실적인 옵션입니다.
생성 된 코드는 릴리스 빌드에서 매우 다를 수 있으며, 자동 생성 배열 구절을 명시 적으로 생성 한 배열 구절 (통화 사이트에서 또는 다른 메소드/생성자/클래스에서 더 멀리있을 수 있습니다.
단서
편집 한 후에이 작업을 수행하려는 이유에 대해서는 속성 기반 주석이 훨씬 더 나은 솔루션이라는 점에 주목해야합니다. 직접 귀속 할 수있는 방법에서 왜이 작업을 수행하고 싶은지 알 수 없습니다 ...
다른 팁
무슨 말인지 잘 모르겠습니다. 그러나 당신의 기능은 실제로 만 얻는다는 것을 주목하십시오 하나 인수 : 배열. 그것이 당신이 일리노이에서 얻는 것입니다. 내부에 함수, 배열을 걸어 가서 그 값을 얻을 수 있습니다.
public static void ToDo( params object[] info ) {
foreach (object x in info)
Console.WriteLine(x);
}