C# 反射:在成员字段上查找属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/803221/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 01:49:26  来源:igfitidea点击:

C# Reflection : Finding Attributes on a Member Field

c#reflectionattributesfield

提问by Hugoware

I may be asking this incorrectly, but can/how can you find fields on a class within itself... for example...

我可能会错误地问这个问题,但是您可以/如何在其内部找到类中的字段......例如......

public class HtmlPart {
  public void Render() {
    //this.GetType().GetCustomAttributes(typeof(OptionalAttribute), false);
  }
}

public class HtmlForm {
  private HtmlPart _FirstPart = new HtmlPart();      
  [Optional] //<-- how do I find that?
  private HtmlPart _SecondPart = new HtmlPart();
}

Or maybe I'm just doing this incorrectly... How can I call a method and then check for attributes applied to itself?

或者,也许我只是做错了……我怎样才能调用一个方法,然后检查应用于自身的属性?

Also, for the sake of the question- I'm just curious if it was possible to find attribute information without knowing/accessing the parent class!

另外,为了这个问题- 我只是好奇是否可以在不知道/访问父类的情况下找到属性信息

采纳答案by bruno conde

If I understand your question correctly, I think what you are trying to do is not possible...

如果我正确理解您的问题,我认为您尝试做的事情是不可能的......

In the Rendermethod, you want to get a possible attribute applied to the object. The attribute belongs to the field _SecondPartwitch belongs to the class HtmlForm.

在该Render方法中,您希望获取应用于对象的可能属性。属性属于字段_SecondPart女巫属于类HtmlForm

For that to work you would have to pass the calling object to the Rendermethod:

为此,您必须将调用对象传递给Render方法:

    public class HtmlPart {
        public void Render(object obj) {
            FieldInfo[] infos = obj.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);

            foreach (var fi in infos)
            {
                if (fi.GetValue(obj) == this && fi.IsDefined(typeof(OptionalAttribute), true))
                    Console.WriteLine("Optional is Defined");
            }
        }
    }

回答by Jon Skeet

You can find fields within a class using Type.GetFields, and you can find attributes applied to a field using MemberInfo.GetCustomAttributesor IsDefined- but if you need to find all the fields of a particular type, you're going to have to:

您可以使用 查找类中的字段Type.GetFields,也可以使用MemberInfo.GetCustomAttributes或查找应用于字段的属性IsDefined- 但如果您需要查找特定类型的所有字段,则必须:

  • Iterate over all the assemblies you want to search
  • Iterate over all the types within each assembly
  • Iterate over all the fields within each type
  • Check for the attribute's presence/absence for each field
  • 迭代您要搜索的所有程序集
  • 迭代每个程序集中的所有类型
  • 迭代每种类型中的所有字段
  • 检查每个字段的属性是否存在

Now, if you're really trying to find out "is a particular attribute applied to a field whose value is a reference to 'this' object" then that's even harder - because you'd have to know all about every object in the system. You should also bear in mind that there could be twofields both with the same value, i.e. referencing the same object. Would the object count as "optional" in that case or not?

现在,如果您真的想找出“是应用于字段的特定属性,其值是对'this'对象的引用”,那么这就更难了 - 因为您必须了解系统中每个对象的所有信息. 您还应该记住,可能有两个字段具有相同的值,即引用同一个对象。在这种情况下,对象是否算作“可选”?

Basically, if the object should have a property (e.g. optional or not) then that must be a property of the object itself, not the field containing the property.

基本上,如果对象应该有一个属性(例如可选或不可选),那么它必须是对象本身的属性,而不是包含该属性的字段。

It could be that I'm misinterpreting what you're trying to do, but I suspectit's either not feasible or at least not a good idea. Could you explain the bigger picture here? What are you really trying to achieve with this attribute?

可能是我误解了你想要做的事情,但我怀疑这要么不可行,要么至少不是一个好主意。你能在这里解释一下更大的图景吗?你真正想用这个属性实现什么?

回答by JoshBerke

Here's an example of given a single object how to find if any public or private fields on that object have a specific property:

这是一个给定单个对象的示例,该示例如何查找该对象上的任何公共或私有字段是否具有特定属性:

var type = typeof(MyObject);
foreach (var field in type.GetFields(BindingFlags.Public |
             BindingFlags.NonPublic | BindingFlags.Instance))
{
    if (field.IsDefined(typeof(ObsoleteAttribute), true))
    {
        Console.WriteLine(field.Name);
    }

}

For the second part of your question you can check if an attribute is defiend on the current method using:

对于问题的第二部分,您可以使用以下方法检查当前方法是否定义了属性:

MethodInfo.GetCurrentMethod().IsDefined(typeof(ObsoleteAttribute));

Edit

编辑

To answer your edit yes it is possible without knowing the actual type. The following function takes a type Parameter and returns all fields which have a given attribute. Someone somewhere is going to either know the Type you want to search, or will have an instance of the type you want to search.

要回答您的编辑是,可能在不知道实际类型的情况下。以下函数采用类型参数并返回具有给定属性的所有字段。某个地方的某个人要么知道您要搜索的类型,要么将拥有您要搜索的类型的实例。

Without that you'd have to do as Jon Skeet said which is to enumerate over all objects in an assembly.

没有它,您就必须像 Jon Skeet 所说的那样枚举程序集中的所有对象。

   public List<FieldInfo> FindFields(Type type, Type attribute)
    {
        var fields = new List<FieldInfo>();
        foreach (var field in type.GetFields(BindingFlags.Public |
                           BindingFlags.NonPublic |
                           BindingFlags.Instance))
        {
            if (field.IsDefined(attribute, true))
            {
                fields.Add(field);
            }

        }
        return fields;
    }