获取属性时如何忽略继承链?

时间:2021-03-25 07:17:55

For some reason I'm not getting this. (Example model below) If I write:

出于某种原因,我没有得到这个。 (下面的示例模型)如果我写:

var property = typeof(sedan).GetProperty("TurningRadius");
Attribute.GetCustomAttributes(property,typeof(MyAttribute), false)

the call will return MyAttribute(2) despite indicating I don't want to search the inheritance chain. Does anyone know what code I can write so that calling

尽管表明我不想搜索继承链,但该调用将返回MyAttribute(2)。有谁知道我可以编写什么代码以便调用

MagicAttributeSearcher(typeof(Sedan).GetProperty("TurningRadius"))

returns nothing while calling

在打电话时什么也不回

MagicAttributeSearcher(typeof(Vehicle).GetProperty("TurningRadius"))

returns MyAttribute(1)?


Example Model:

public class Sedan : Car
{
    // ...
}

public class Car : Vehicle
{
    [MyAttribute(2)]
    public override int TurningRadius { get; set; }
}

public abstract class Vehicle
{
    [MyAttribute(1)]
    public virtual int TurningRadius { get; set; }
}

3 个解决方案

#1


4  

Okay, given the extra information - I believe the problem is that GetProperty is going up the inheritance change.

好的,鉴于额外的信息 - 我认为问题是GetProperty正在进行继承更改。

If you change your call to GetProperty to:

如果您将对GetProperty的调用更改为:

PropertyInfo prop = type.GetProperty("TurningRadius",
    BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);

then prop will be null if the property isn't overridden. For instance:

如果不覆盖该属性,则prop将为null。例如:

static bool MagicAttributeSearcher(Type type)
{
    PropertyInfo prop = type.GetProperty("TurningRadius", BindingFlags.Instance | 
                                         BindingFlags.Public | BindingFlags.DeclaredOnly);

    if (prop == null)
    {
        return false;
    }
    var attr = Attribute.GetCustomAttribute(prop, typeof(MyAttribute), false);
    return attr != null;
}

This returns true and only if:

这返回true,仅在以下情况下:

  • The specified type overrides the TurningRadius property (or declares a new one)
  • 指定的类型会覆盖TurningRadius属性(或声明一个新属性)

  • The property has the MyAttribute attribute.
  • 该属性具有MyAttribute属性。

#2


3  

I believe the problem is that when you obtain the property TurningRadius from the Sedan object in the first line

我相信问题是当你从第一行的Sedan对象获得属性TurningRadius时

var property = typeof(sedan).GetProperty("TurningRadius");

what you are actually getting is the TurningRadius property declared at Car level, since Sedan doesn't have its own overload.

你实际得到的是在Car级别声明的TurningRadius属性,因为Sedan没有自己的重载。

Therefore, when you request its attributes, you are getting the ones defined at car even if you requested not to go up in the inheritance chain, as the property you are querying is the one defined in Car.

因此,当您请求其属性时,即使您请求不在继承链中,您也会获得在汽车中定义的属性,因为您要查询的属性是Car中定义的属性。

You should change the GetProperty to add the necessary flags to obtain only declaring members. I believe DeclaredOnly should do.

您应该更改GetProperty以添加必要的标志以仅获取声明成员。我相信DeclaredOnly应该这样做。

Edit: Note that this change will have the first line return null, so watch out for NullPointerExceptions.

编辑:请注意,此更改将使第一行返回null,因此请注意NullPointerExceptions。

#3


1  

I think this is what you're after - note that I had to make TurningRadius abstract in Vehicle and overridden in Car. Is that okay?

我认为这就是你所追求的 - 请注意我必须在Vehicle中使TurningRadius抽象并在Car中重写。这样可以吗?

using System;
using System.Reflection;

public class MyAttribute : Attribute
{
    public MyAttribute(int x) {}
}

public class Sedan : Car
{
    // ...
}

public class Car : Vehicle
{
    public override int TurningRadius { get; set; }
}

public abstract class Vehicle
{
    [MyAttribute(1)]
    public virtual int TurningRadius { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        MagicAttributeSearcher(typeof(Sedan));
        MagicAttributeSearcher(typeof(Vehicle));
    }

    static void MagicAttributeSearcher(Type type)
    {
        PropertyInfo prop = type.GetProperty("TurningRadius");
        var attr = Attribute.GetCustomAttribute(prop, typeof(MyAttribute), false);
        Console.WriteLine("{0}: {1}", type, attr);
    }
}

Output:

Sedan:
Vehicle: MyAttribute

#1


4  

Okay, given the extra information - I believe the problem is that GetProperty is going up the inheritance change.

好的,鉴于额外的信息 - 我认为问题是GetProperty正在进行继承更改。

If you change your call to GetProperty to:

如果您将对GetProperty的调用更改为:

PropertyInfo prop = type.GetProperty("TurningRadius",
    BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);

then prop will be null if the property isn't overridden. For instance:

如果不覆盖该属性,则prop将为null。例如:

static bool MagicAttributeSearcher(Type type)
{
    PropertyInfo prop = type.GetProperty("TurningRadius", BindingFlags.Instance | 
                                         BindingFlags.Public | BindingFlags.DeclaredOnly);

    if (prop == null)
    {
        return false;
    }
    var attr = Attribute.GetCustomAttribute(prop, typeof(MyAttribute), false);
    return attr != null;
}

This returns true and only if:

这返回true,仅在以下情况下:

  • The specified type overrides the TurningRadius property (or declares a new one)
  • 指定的类型会覆盖TurningRadius属性(或声明一个新属性)

  • The property has the MyAttribute attribute.
  • 该属性具有MyAttribute属性。

#2


3  

I believe the problem is that when you obtain the property TurningRadius from the Sedan object in the first line

我相信问题是当你从第一行的Sedan对象获得属性TurningRadius时

var property = typeof(sedan).GetProperty("TurningRadius");

what you are actually getting is the TurningRadius property declared at Car level, since Sedan doesn't have its own overload.

你实际得到的是在Car级别声明的TurningRadius属性,因为Sedan没有自己的重载。

Therefore, when you request its attributes, you are getting the ones defined at car even if you requested not to go up in the inheritance chain, as the property you are querying is the one defined in Car.

因此,当您请求其属性时,即使您请求不在继承链中,您也会获得在汽车中定义的属性,因为您要查询的属性是Car中定义的属性。

You should change the GetProperty to add the necessary flags to obtain only declaring members. I believe DeclaredOnly should do.

您应该更改GetProperty以添加必要的标志以仅获取声明成员。我相信DeclaredOnly应该这样做。

Edit: Note that this change will have the first line return null, so watch out for NullPointerExceptions.

编辑:请注意,此更改将使第一行返回null,因此请注意NullPointerExceptions。

#3


1  

I think this is what you're after - note that I had to make TurningRadius abstract in Vehicle and overridden in Car. Is that okay?

我认为这就是你所追求的 - 请注意我必须在Vehicle中使TurningRadius抽象并在Car中重写。这样可以吗?

using System;
using System.Reflection;

public class MyAttribute : Attribute
{
    public MyAttribute(int x) {}
}

public class Sedan : Car
{
    // ...
}

public class Car : Vehicle
{
    public override int TurningRadius { get; set; }
}

public abstract class Vehicle
{
    [MyAttribute(1)]
    public virtual int TurningRadius { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        MagicAttributeSearcher(typeof(Sedan));
        MagicAttributeSearcher(typeof(Vehicle));
    }

    static void MagicAttributeSearcher(Type type)
    {
        PropertyInfo prop = type.GetProperty("TurningRadius");
        var attr = Attribute.GetCustomAttribute(prop, typeof(MyAttribute), false);
        Console.WriteLine("{0}: {1}", type, attr);
    }
}

Output:

Sedan:
Vehicle: MyAttribute