【问题标题】:How to decompile .Net events?如何反编译 .Net 事件?
【发布时间】:2016-04-10 13:34:07
【问题描述】:

Xamarin Assebly 浏览器为事件生成以下代码

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)

【问题讨论】:

  • 那是因为 Xamarin 反编译器不处理事件的二元性。事件标识符可以在内部用作字段,但在外部用作事件。反编译器应该将其反编译为字段,但它没有,而是将其反编译为带有添加/删除访问器的显式事件声明。这使得对事件的所有访问都作为字段非法。

标签: c# .net events xamarin disassembly


【解决方案1】:

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

public event EventHandler EventName;

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

  1. 一个字段,保存事件的委托
  2. 一个事件,声明添加和删除访问器来操作此字段

但是,您仍然只有一个标识符,EventName,但其确切含义取决于其上下文:

  1. 当您在声明事件的类中时对该字段的引用
  2. 当您在声明事件的类之外时对事件的引用

实际上,创建了这样的代码:

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 反编译器不理解这种双重含义。基本上你将不得不根据上面的例子重写代码。

【讨论】:

  • 不明白你的意思。
  • 你用一个来称呼它,但请不要让这个问题成为一个移动的目标。如果您有新问题,请提出新问题,不要一直添加到这个问题。
  • 只用一个布尔参数调用事件处理程序。
  • 我发布了可以正常定义事件的代码,采用object sender, SomethingSomethingEventArgs e 参数列表,您没有像那样声明您的事件,所以不,您不应该传递this,只有你的布尔参数值。
  • 是的,没错。所以你可以用evt(true);之类的东西来称呼它
猜你喜欢
  • 1970-01-01
  • 2012-08-03
  • 2011-01-17
  • 1970-01-01
  • 2011-09-11
  • 2020-01-22
  • 1970-01-01
  • 2021-03-04
  • 2011-07-09
相关资源
最近更新 更多