在.NET中反映类会产生仅因修饰符而异的方法

时间:2010-04-17 20:17:54

标签: c# .net clr

我对某些东西感到有些困惑,我希望CLR减速机可以提供帮助。显然我的齿轮不够大。

我有一个反射器实用程序,它为Cola for .NET生成程序集存根,我发现类的方法只有一个修饰符不同,例如virtual。以下示例,来自Oracle.DataAccess.dll,方法GetType():

class OracleTypeException : System.SystemException {
    virtual  string ToString ();
    virtual  System.Exception GetBaseException ();
    virtual  void set_Source (string value);
    virtual  void GetObjectData (System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context);
    virtual  System.Type GetType (); // DeclaringType Exception
    virtual  bool Equals (object obj);
    virtual  int32 GetHashCode ();
    System.Type GetType (); // DeclaringType Object
}

这是什么?

我无法使用C#重现这一点,因为它认为GetType()是重新定义,因此可能会给Cola带来麻烦,因为签名是相同的。

我的方法反射器就像这样开始:

static void DisplayMethod(MethodInfo m)
{
    if (
       // Filter out things Cola cannot yet import, like generics, pointers, etc.
       m.IsGenericMethodDefinition || m.ContainsGenericParameters || m.ReturnType.IsGenericType
       || !m.ReturnType.IsPublic
       || m.ReturnType.IsPointer || m.ReturnType.IsByRef
       || m.ReturnType.IsMarshalByRef
       || m.ReturnType.IsImport
       )
   return;

   // generate stub signature
   // [snipped]
}

解决: 非虚拟GetType()来自System.Object。派生类使用虚方法阴影化System.Object.GetType()。

3 个答案:

答案 0 :(得分:3)

我会检查:

  • 是静态的吗?
  • 是隐式接口实现吗?

请注意,您也可以重新声明方法,这可能是一个因素;但那会很疯狂;但是,这表明了这一点:

class Bar {
    new Type GetType() { return null; }
}
static class Program {
    static void Main() {
        var methods = typeof(Bar).GetMethods(
              BindingFlags.Instance | BindingFlags.Static
            | BindingFlags.Public | BindingFlags.NonPublic);
        foreach (var method in methods) {
            Console.WriteLine(method.Name);
        }
    }
}

答案 1 :(得分:3)

这是可能的。这是一个编译得很好的代码片段:

public class OracleTypeException : SystemException, _Exception
{
    public virtual Type GetType()
    {
        throw new NotImplementedException();
    }

    Type _Exception.GetType()
    {
        throw new NotImplementedException();
    }
}

它依赖于SystemException实现_Exception的事实,GetType本身定义了an explicit implementation方法。所以我们有:

  1. {{3}}此界面
  2. 一个GetType方法,它隐藏来自System.Object的方法。
  3. 顺便说一句,编译器会生成一个关于它的警告。

答案 2 :(得分:1)

此类应表现出相同的行为:

  class Something {
    public virtual Type GetType() {
      throw new NotImplementedException();
    }
  }

由于每个类都继承自System.Object,因此它还继承了非虚拟 Object.GetType()方法。将方法重新声明为虚拟(请注意,甚至不需要“new”关键字)隐藏原始继承的GetType方法。

不确定这个工具需要什么,但我想你需要用“Object_GetType”重命名隐藏的继承方法。