如何反编译.Net事件?

时间:2016-04-10 13:34:08

标签: c# .net events xamarin disassembly

Xamarin Assebly Browser为事件生成以下代码

public event BooleanPreference.ValueChangedHandler ValueChanged {
    [MethodImpl (MethodImplOptions.Synchronized)]
    add {
        this.ValueChanged = (BooleanPreference.ValueChangedHandler)Delegate.Combine (this.ValueChanged, value);
    }
    [MethodImpl (MethodImplOptions.Synchronized)]
    remove {
        this.ValueChanged = (BooleanPreference.ValueChangedHandler)Delegate.Remove (this.ValueChanged, value);
    }
}

编译它会产生错误,例如

Error CS0079: The event `EdB.Interface.BooleanPreference.ValueChanged' can only appear on the left hand side of `+=' or `-=' operator (CS0079) (EdB.Interface)

如何转换代码才能使其正常工作?

稍后在代码中,该事件在

中引用
if ((!flag.HasValue || flag.Value != this.boolValue) && this.ValueChanged != null) {
    this.ValueChanged (value);
}

造成同样的错误

Error CS0079: The event `EdB.Interface.BooleanPreference.ValueChanged' can only appear on the left hand side of `+=' or `-=' operator (CS0079) (EdB.Interface)

编辑:

以下代码

public delegate void ValueChangedHandler (bool value);

public event BooleanPreference.ValueChangedHandler ValueChanged;

protected void OnValueChanged(EventArgs e) {
    var evt = ValueChanged;
    if (evt != null) {
        evt(this, e);
    }
}

产生

Error CS1593: Delegate `EdB.Interface.BooleanPreference.ValueChangedHandler' does not take `2' arguments (CS1593) (EdB.Interface)

1 个答案:

答案 0 :(得分:2)

C#中的基本事件声明,如下所示:

public event EventHandler EventName;

最终会给你一个标识符EventName,它有两个含义,因为编译器使用单个声明来创建两个东西:

  1. 一个字段,持有该事件的代表
  2. 一个事件,声明添加和删除访问器以操纵此字段
  3. 但是,您仍然只有一个标识符EventName,但其确切含义取决于其上下文:

    1. 只要您在声明事件的类中
    2. ,就会引用该字段
    3. 当您在宣布该事件的类之外时,对该事件的引用
    4. 实际上,创建了这种代码:

      private EventHandler _EventName;
      
      public event EventHandler EventName
      {
          add
          {
              _EventName = (EventHandler)Delegate.Combine(_EventName, value);
          }
          remove
          {
              _EventName = (EventHandler)Delegate.Remove(_EventName, value);
          }
      }
      

      但是,由于您使用基本语法来声明事件,编译器将默默地修复所有引用,以引用字段(在类内)或事件(在类外)。

      这是您要编写的OnEventName方法的示例:

      protected void OnEventName(...)
      {
          var evt = EventName;
          if (evt != null)
              evt(this, ...);
      }
      

      编译器会默默地将其重写为:

      protected void OnEventName(...)
      {
          var evt = _EventName; // reference to the field
          if (evt != null)
              evt(this, ...);
      }
      

      显然,Xamarin反编译器并不了解这种双重含义。基本上你必须根据上面的例子重写代码。