2017-04-21 39 views
0

我有这样一些代码的实例中使用的所有类型:写一个测试,以找到一个类

new ValidationFailure<AddSystemUserDto> 

这是在我的应用服务层不同的地方,我想找到所有不同的“DTO “在代码中新增ValidationFailure时使用的类型,这是否可以使用反射?无需运行每个应用程序服务方法?

+0

_“这是可能使用反射” _ - 可能,但这需要你通过所有方法去挖掘,并找到所有'公共无效美孚(){返回新ValidationFailure ( ); }并且调用这个方法,这是一个令人厌恶的事情。您宁愿在编译时或之前使用静态分析,例如通过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); 
     } 
    } 
} 

从这一点来说,剩下的就是找到你调用构造函数时所使用的所有类型的问题(注:未经测试的代码,有可能出错:-):

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; 
       } 
      } 
     } 
    } 
} 
}