2016-08-03 15 views
1

Из любопытства я решил попробовать декомпилировать код моего проекта. Я взял файл .dll Ассамблеи и использовал ILSpy для его декомпиляции. Кажется, что он работает правильно, за исключением методов IEnumerator<>.Декомпиляция IEnumerators

IEnumerator sP() 
{ 
     for (int i = 0; i < maxEnemies; i++) 
     { 
      var p = Porczaks[Random.Range(0, Porczaks.Length)]; 
      Instantiate(p, new Vector3(Random.Range(245, 360), 16.8f, Random.Range(292, 366)), Quaternion.Euler(0f, Random.Range(0f, 359f), 0f)); 
      yield return new WaitForEndOfFrame(); 
     } 
} 

... это, например, декодируется в этом:

[DebuggerHidden] 
private IEnumerator sP() 
{ 
    WaveManager.<sP>c__Iterator7 <sP>c__Iterator = new WaveManager.<sP>c__Iterator7(); 
    <sP>c__Iterator.<>f__this = this; 
    return <sP>c__Iterator; 
} 

Есть ли способ, чтобы точно декомпилировать, что IEnumerator?

EDIT: Я декомпилировал же сборку с помощью декомпилятор dotPeek, и он создал способом больше коды. Хотя я до сих пор не уверен, что переменные могут иметь такие имена в .net:

// Method sP with token 060000AB 
[/*Attribute with token 0C000051*/DebuggerHidden] 
private IEnumerator sP() 
{ 
    WaveManager.\u003CsP\u003Ec__Iterator7 sPCIterator7 = new WaveManager.\u003CsP\u003Ec__Iterator7(); 
    sPCIterator7.\u003C\u003Ef__this = this; 
    return (IEnumerator) sPCIterator7; 
} 

// Type <sP>c__Iterator7 with token 02000031 
[/*Attribute with token 0C000026*/CompilerGenerated] 
private sealed class \u003CsP\u003Ec__Iterator7 : IEnumerator<object>, IEnumerator, IDisposable 
{ 
    // Field <i>__0 with token 040000C7 
    internal int \u003Ci\u003E__0; 
    // Field <p>__1 with token 040000C8 
    internal GameObject \u003Cp\u003E__1; 
    // Field $PC with token 040000C9 
    internal int \u0024PC; 
    // Field $current with token 040000CA 
    internal object \u0024current; 
    // Field <>f__this with token 040000CB 
    internal WaveManager \u003C\u003Ef__this; 

    // Property System.Collections.Generic.IEnumerator<object>.Current with token 17000017 
    object IEnumerator<object>.System\u002ECollections\u002EGeneric\u002EIEnumerator\u003Cobject\u003E\u002ECurrent 
    { 
     // Method System.Collections.Generic.IEnumerator<object>.get_Current with token 060000EA 
     [/*Attribute with token 0C00006E*/DebuggerHidden] get 
     { 
     return this.\u0024current; 
     } 
    } 

    // Property System.Collections.IEnumerator.Current with token 17000018 
    object IEnumerator.Current 
    { 
     // Method System.Collections.IEnumerator.get_Current with token 060000EB 
     [/*Attribute with token 0C00006F*/DebuggerHidden] get 
     { 
     return this.\u0024current; 
     } 
    } 

    // Method .ctor with token 060000E9 
    public \u003CsP\u003Ec__Iterator7() 
    { 
     base.\u002Ector(); 
    } 

    // Method MoveNext with token 060000EC 
    public bool MoveNext() 
    { 
     uint num = (uint) this.\u0024PC; 
     this.\u0024PC = -1; 
     switch (num) 
     { 
     case 0: 
      this.\u003Ci\u003E__0 = 0; 
      break; 
     case 1: 
      this.\u003Ci\u003E__0 = this.\u003Ci\u003E__0 + 1; 
      break; 
     default: 
      return false; 
     } 
     if (this.\u003Ci\u003E__0 < this.\u003C\u003Ef__this.maxEnemies) 
     { 
     this.\u003Cp\u003E__1 = this.\u003C\u003Ef__this.Porczaks[UnityEngine.Random.Range(0, this.\u003C\u003Ef__this.Porczaks.Length)]; 
     UnityEngine.Object.Instantiate((UnityEngine.Object) this.\u003Cp\u003E__1, new Vector3((float) UnityEngine.Random.Range(245, 360), 16.8f, (float) UnityEngine.Random.Range(292, 366)), Quaternion.Euler(0.0f, UnityEngine.Random.Range(0.0f, 359f), 0.0f)); 
     this.\u0024current = (object) new WaitForEndOfFrame(); 
     this.\u0024PC = 1; 
     return true; 
     } 
     this.\u0024PC = -1; 
     goto default; 
    } 

    // Method Dispose with token 060000ED 
    [/*Attribute with token 0C000070*/DebuggerHidden] 
    public void Dispose() 
    { 
     this.\u0024PC = -1; 
    } 

    // Method Reset with token 060000EE 
    [/*Attribute with token 0C000071*/DebuggerHidden] 
    public void Reset() 
    { 
     throw new NotSupportedException(); 
    } 
} 

Кажется dotPeek не обрабатывал < и > правильно, но этот код стоит что-нибудь?

+0

Это действительно похоже на то, что генерирует компилятор. – Enigmativity

+0

Сказав, что JetBrains dotPeek, похоже, лучше справляется с этим. – Enigmativity

+0

Я проверил dotPeek, и при отображении токенов отключен в коде, он выглядит почти так же, как код от ILSpy, но с включенным он становится действительно запутанным. Я разместил код в первом сообщении. Это имеет смысл? Будет ли это работать, если я просто изменил имена с ' __ + @! #' На что-то нормальное? – Reynevan

ответ

1

Вы действительно видите код шаблона, который генерирует компилятор, чтобы заменить оператор возврата доходности. И да, это действительно государственная машина.

Обычно декомпилятор должен распознавать код шаблона, сгенерированный компилятором, и заменять его правильной операцией C#. Это признание, однако, выполняется путем сопоставления с образцом, то есть ожидается, что код шаблона будет структурирован очень определенным образом. Если компилятор создает эквивалентный код, но с другой структурой (например, из-за обновления компилятора, оптимизации и т. Д.), То декомпилятор не сможет сопоставить шаблон и распознать инструкцию yield.

Что вы должны сделать, это отправить отчет об ошибках в команды декомпилятора, чтобы это стало фиксированным, и вам не нужно вручную переименовывать материал. Вы пробовали JustDecompile на этой сборке? Это тоже не так? Если это так, вы можете опубликовать это на форумах Telerik, и мы позаботимся об этом.

На стороне заметки, какой компилятор вы использовали?