如果绑定名称是GetType()或ToString()等,则TryInvokeMember不会触发

本文关键字:TryInvokeMember ToString 定名称 绑定 GetType 如果 | 更新日期: 2023-09-27 18:05:29

我只是在摆弄c# 4.0动态关键字,对一件事很好奇。

假设我有一个类DynamicWeirdness : DynamicObject

里面我有一个名为reference的字段,它的类型也是dynamic。还有一个名为referencetype的字段,类型为Type

这是我的构造函数:
public DynamicWeirdness(object reference)
{
        this.reference = reference;
        this.referencetype = reference.GetType();
}

如果我试过:

public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
    if (binder.Name == "GetType" && args.Length == 0)
    {
        result =  referencetype;
        return true;
    }
    result = null;
    return false;
}

当我调用DynamicWeirdness对象的GetType()时,它只是忽略我的调用并返回{Name = "DynamicWeirdness" FullName = "Dynamic1.DynamicWeirdness"}。为什么?

我试过ToString(), GetHashCode(),同样的事情发生了

如果绑定名称是GetType()或ToString()等,则TryInvokeMember不会触发

根据DynamicObject文档:

还可以将自己的成员添加到从DynamicObject类派生的类中。如果你的类定义属性,并覆盖动态语言TrySetMember方法运行时(DLR)首先使用语言绑定器查找属性的静态定义在课堂上。如果没有这样的属性,DLR调用TrySetMember方法。

由于DynamicObject继承自Object, Object的任何方法都将阻止TryInvokeMember处理调用

方法GetType()ToString()GetHashCode()都是在DynamicObject上定义的(因为它继承自System.Object)。当。net调用这些方法时,它将直接调用它们,因为它们是在对象上定义的,并且将跳过对TryInvokeMember的调用。

如果你尝试调用不同的方法,比如Substring(),你会看到DynamicWeirdness上的TryInvokeMember确实被调用了。

您可以在DynamicWeirdness上创建一个新的GetType()方法,而不是在DynamicWeirdness上重写TryInvokeMember以返回不同的类型。

public new Type GetType()
{
    return this.referencetype;
}
对于GetHashCode()ToString(),可以在DynamicWeirdness上重写这些成员,因为它们被标记为virtual。