如何反思告诉我,当一个属性是隐藏一个继承的成员与'新'的关键字? [英] How does reflection tell me when a property is hiding an inherited member with the 'new' keyword?

查看:136
本文介绍了如何反思告诉我,当一个属性是隐藏一个继承的成员与'新'的关键字?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以,如果我有:

public class ChildClass : BaseClass
{
    public new virtual string TempProperty { get; set; }
}

public class BaseClass
{
    public virtual string TempProperty { get; set; }
}



我如何使用反射来看到ChildClass被隐藏的基实现TempProperty?

How can I use reflection to see that ChildClass is hiding the Base implementation of TempProperty?

我想答案是C#之间无关,vb.net

I'd like the answer to be agnostic between c# and vb.net

推荐答案

我们必须处理的财产的方法,在这里,而不是物业本身来讲,因为它是真正得到覆盖,而不是物业本身的属性的get / set方法。我将使用GET方法,你永远不应该有一个属性没有之一,但一个完整的解决方案应检查缺一。

We'll have to deal in terms of the methods of the property here rather than the property itself, because it is the get/set methods of the property that actually get overridden rather than the property itself. I'll use the get method as you should never have a property without one, though a complete solution should check for the lack of one.

综观发出的IL很多情况下,基础属性的'得到'的方法将有元数据标记(这是从C#编译器;其他人可能不会发射 hidebysig 取决于他们的方法藏语义,在这种情况下,该方法将是隐藏按姓名):

Looking at the IL emitted in a number of cases, the 'get' method of the base property will have the metadata tokens (this is from the C# compiler; others may not emit the hidebysig depending on their method hiding semantics, in which case the method would be hide-by-name):

non-virtual : .method public hidebysig specialname instance
virtual     : .method public hidebysig specialname newslot virtual instance

派生的人会拥有以下标记:

The derived one will have the following tokens:

override    : .method public hidebysig specialname virtual instance 
new         : .method public hidebysig specialname instance
new virtual : .method public hidebysig specialname newslot virtual instance

因此,我们可以从这个看到它无法从方法的元数据标记纯告诉它是否是,因为非虚基类方法具有相同的标记作为非虚法,虚基方法具有相同的标记作为新的虚拟方法。

So we can see from this that it isn't possible to tell purely from the method's metadata tokens whether it is new because the non-virtual base method has the same tokens as the non-virtual new method, and the virtual base method has the same tokens as the new virtual method.

我们的可以的说的是,如果该方法具有虚拟标记,而不是 newslot 标记然后重写基方法,而不是它的阴影,即

What we can say is that if the method has the virtual token but not the newslot token then it overrides a base method rather than shadows it, i.e.

var prop = typeof(ChildClass).GetProperty("TempProperty");
var getMethod = prop.GetGetMethod();
if ((getMethod.Attributes & MethodAttributes.Virtual) != 0 &&
    (getMethod.Attributes & MethodAttributes.NewSlot) == 0)
{
    // the property's 'get' method is an override
}

假设,那么,我们找到了'得到'方法不是一个覆盖,我们想知道是否有它遮蔽了基类的属性。的问题是,由于该方法是在一个不同的方法表槽,它实际上并不必须被遮蔽的方法的任何直接关系。那么,我们实际上说的是没有基本类型有哪些符合标准的遮蔽任何方法,这取决于方法是否是 hidebysig 或隐藏逐-名称。

Assuming, then, that we find the 'get' method is not an override, we want to know whether there is a property in the base class that it is shadowing. The problem is that because the method is in a different method table slot, it doesn't actually have any direct relationship to the method it is shadowing. So what we're actually saying is "does the base type have any method which meets the criteria for shadowing", which varies depending on whether the method is hidebysig or hide-by-name.

对于前者,我们需要检查的基类是否有其签名的完全匹配,而对于后者,我们需要检查是否有与任何方法的任何方法相同的名称,因此继续从上面的代码:

For the former we need to check whether the base class has any method which matches the signature exactly, whereas for the latter we need to check whether it has any method with the same name, so continuing the code from above:

else 
{
    if (getMethod.IsHideBySig)
    {
        var flags = getMethod.IsPublic ? BindingFlags.Public : BindingFlags.NonPublic;
        flags |= getMethod.IsStatic ? BindingFlags.Static : BindingFlags.Instance;
        var paramTypes = getMethod.GetParameters().Select(p => p.ParameterType).ToArray();
        if (getMethod.DeclaringType.BaseType.GetMethod(getMethod.Name, flags, null, paramTypes, null) != null)
        {
            // the property's 'get' method shadows by signature
        }
    }
    else
    {
        var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance;
        if (getMethod.DeclaringType.BaseType.GetMethods(flags).Any(m => m.Name == getMethod.Name))
        {
            // the property's 'get' method shadows by name
        }
    }
}

我觉得这是大多数的方式,但我仍然不认为这是完全正确的。因为一开始我不完全熟悉隐藏的名字为C#不支持它,这几乎是所有我用,所以我可能是错在这里代码表明实例方法可以影静态的。我也不知道是否区分大小写的问题(例如,在VB中可以被称为方法阴影调用方法如果他们都具有相同的签名,均 hidebysig - 在C#中的答案是否定的,但如果答案是肯定的在VB那么就意味着这个问题的答案其实是不确定的)。

I think this is most of the way there, but I still don't think it's exactly right. For a start I'm not totally familiar with hiding by name as C# doesn't support it and that's pretty much all I use, so I may be wrong in the code here that indicates an instance method could shadow a static one. I also don't know about the case sensitivity issue (e.g. in VB could a method called Foo shadow a method called foo if they both had the same signature and were both hidebysig - in C# the answer is no but if the answer is yes in VB then it means the answer to this question is actually nondeterministic).

好吧,我不知道有多少帮助,这一切,除了说明它实际上是一个更难的问题比我想象的要(还是我错过了一些真的很明显在这种情况下,我想知道的!)。但希望它有足够的内容,它可以帮助你实现你想要做的事。

Well, I'm not sure how much help all this is, other than to illustrate that it's actually a much harder problem than I thought it would be (or I've missed something really obvious in which case I'd like to know!). But hopefully it's got sufficient content that it helps you achieve what you're trying to do.

这篇关于如何反思告诉我,当一个属性是隐藏一个继承的成员与'新'的关键字?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆