2017-04-21 15 views
0

클래스의 인스턴스에 사용 된 모든 종류의 찾기 위해 테스트를 쓰기 : 이것은 내 응용 프로그램 서비스 계층에서 다양한 장소에내가 좋아하는 몇 가지 코드가

new ValidationFailure<AddSystemUserDto> 

을, 나는 모든 다른 "DTO를 찾으려면 "코드에서 ValidationFailure를 새로 만들 때 사용 된 유형은 리플렉션을 사용하여 가능합니까? 각 응용 프로그램 서비스 메소드를 실행하지 않고도?

+0

_ _ "이 가능하여 반영"); }'그리고 그 메쏘드, ad nauseum을 호출합니다. 컴파일시 또는 컴파일시에 ReSharper 나 Roslyn과 같은 정적 분석을 사용하여이 작업을 수행하는 것이 좋습니다. 당신은 확실히 그것을 스스로 코딩하고 싶지 않습니다. – CodeCaster

답변

0

예.

이러한 종류의 작업에는 약간의 도우미 클래스가 사용됩니다. 편리하게는 Decompiler을 호출합니다. 기본적으로는 옵 코드에 [] .NET 코드의 바이트 변환 :이 시점에서

public class ILInstruction 
{ 
    public ILInstruction(int offset, OpCode code, object operand) 
    { 
     this.Offset = offset; 
     this.Code = code; 
     this.Operand = operand; 
    } 

    // Fields 
    public int Offset { get; private set; } 
    public OpCode Code { get; private set; } 
    public object Operand { get; private set; } 
} 

internal class Decompiler 
{ 
    private Decompiler() { } 

    static Decompiler() 
    { 
     InitDecompiler(); 
    } 

    private static OpCode[] singleByteOpcodes; 
    private static OpCode[] multiByteOpcodes; 

    private static void InitDecompiler() 
    { 
     singleByteOpcodes = new OpCode[0x100]; 
     multiByteOpcodes = new OpCode[0x100]; 
     FieldInfo[] infoArray1 = typeof(OpCodes).GetFields(); 
     for (int num1 = 0; num1 < infoArray1.Length; num1++) 
     { 
      FieldInfo info1 = infoArray1[num1]; 
      if (info1.FieldType == typeof(OpCode)) 
      { 
       OpCode code1 = (OpCode)info1.GetValue(null); 
       ushort num2 = (ushort)code1.Value; 
       if (num2 < 0x100) 
       { 
        singleByteOpcodes[(int)num2] = code1; 
       } 
       else 
       { 
        if ((num2 & 0xff00) != 0xfe00) 
        { 
         throw new Exception("Invalid opcode: " + num2.ToString()); 
        } 
        multiByteOpcodes[num2 & 0xff] = code1; 
       } 
      } 
     } 
    } 

    public static IEnumerable<ILInstruction> Decompile(MethodBase mi, byte[] ildata) 
    { 
     Module module = mi.Module; 

     ByteReader reader = new ByteReader(ildata); 
     while (!reader.Eof) 
     { 
      OpCode code = OpCodes.Nop; 

      int offset = reader.Position; 
      ushort b = reader.ReadByte(); 
      if (b != 0xfe) 
      { 
       code = singleByteOpcodes[b]; 
      } 
      else 
      { 
       b = reader.ReadByte(); 
       code = multiByteOpcodes[b]; 
       b |= (ushort)(0xfe00); 
      } 

      object operand = null; 
      switch (code.OperandType) 
      { 
       case OperandType.InlineBrTarget: 
        operand = reader.ReadInt32() + reader.Position; 
        break; 
       case OperandType.InlineField: 
        if (mi is ConstructorInfo) 
        { 
         operand = module.ResolveField(reader.ReadInt32(), mi.DeclaringType.GetGenericArguments(), Type.EmptyTypes); 
        } 
        else 
        { 
         operand = module.ResolveField(reader.ReadInt32(), mi.DeclaringType.GetGenericArguments(), mi.GetGenericArguments()); 
        } 
        break; 
       case OperandType.InlineI: 
        operand = reader.ReadInt32(); 
        break; 
       case OperandType.InlineI8: 
        operand = reader.ReadInt64(); 
        break; 
       case OperandType.InlineMethod: 
        try 
        { 
         if (mi is ConstructorInfo) 
         { 
          operand = module.ResolveMember(reader.ReadInt32(), mi.DeclaringType.GetGenericArguments(), Type.EmptyTypes); 
         } 
         else 
         { 
          operand = module.ResolveMember(reader.ReadInt32(), mi.DeclaringType.GetGenericArguments(), mi.GetGenericArguments()); 
         } 
        } 
        catch 
        { 
         operand = null; 
        } 
        break; 
       case OperandType.InlineNone: 
        break; 
       case OperandType.InlineR: 
        operand = reader.ReadDouble(); 
        break; 
       case OperandType.InlineSig: 
        operand = module.ResolveSignature(reader.ReadInt32()); 
        break; 
       case OperandType.InlineString: 
        operand = module.ResolveString(reader.ReadInt32()); 
        break; 
       case OperandType.InlineSwitch: 
        int count = reader.ReadInt32(); 
        int[] targetOffsets = new int[count]; 
        for (int i = 0; i < count; ++i) 
        { 
         targetOffsets[i] = reader.ReadInt32(); 
        } 
        int pos = reader.Position; 
        for (int i = 0; i < count; ++i) 
        { 
         targetOffsets[i] += pos; 
        } 
        operand = targetOffsets; 
        break; 
       case OperandType.InlineTok: 
       case OperandType.InlineType: 
        try 
        { 
         if (mi is ConstructorInfo) 
         { 
          operand = module.ResolveMember(reader.ReadInt32(), mi.DeclaringType.GetGenericArguments(), Type.EmptyTypes); 
         } 
         else 
         { 
          operand = module.ResolveMember(reader.ReadInt32(), mi.DeclaringType.GetGenericArguments(), mi.GetGenericArguments()); 
         } 
        } 
        catch 
        { 
         operand = null; 
        } 
        break; 
       case OperandType.InlineVar: 
        operand = reader.ReadUInt16(); 
        break; 
       case OperandType.ShortInlineBrTarget: 
        operand = reader.ReadSByte() + reader.Position; 
        break; 
       case OperandType.ShortInlineI: 
        operand = reader.ReadSByte(); 
        break; 
       case OperandType.ShortInlineR: 
        operand = reader.ReadSingle(); 
        break; 
       case OperandType.ShortInlineVar: 
        operand = reader.ReadByte(); 
        break; 

       default: 
        throw new Exception("Unknown instruction operand; cannot continue. Operand type: " + code.OperandType); 
      } 

      yield return new ILInstruction(offset, code, operand); 
     } 
    } 
} 

를, 나머지는 생성자를 호출 할 때 사용하는 모든 유형을 찾는 문제이다 (참고 : 테스트되지 않은 코드를 잘못 뭔가 거기에 아마 :-) - 아마,하지만 (모든 방법을 통해 발굴하도록 요구하고, 또한 모든`공공 무효 푸 () {ValidationFailure 새로운 돌아 찾을 것

IEnumerable<Type> FindDtoTypes() 
{ 
foreach (var item in GetType().Assembly.GetTypes()) 
{ 
    foreach (var member in type.GetMembers(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance)) 
    { 
     var meth = member as MethodBase; 
     if (meth != null && meth.GetMethodBody() != null) 
     { 
      var code = meth.GetMethodBody().GetILAsByteArray(); 
      foreach (var instr in Decompile(meth, code)) 
      { 
       var oper = instr.Operand as MethodBase; 
       if (oper != null && oper.IsConstructor && 
        oper.DeclaringType.IsGenericType) 
       { 
        var dtoType = mb.DeclaringType.GetGenericArguments().First(); 

        if (dtoType.IsAssignableFrom(oper.DeclaringType)) 
         yield return oper.DeclaringType; 
       } 
      } 
     } 
    } 
} 
}