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

Hug*_*are 16 c# reflection attributes field

我可能会错误地问这个问题,但可以/如何在自己的课程中找到字段......例如......

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();
}
Run Code Online (Sandbox Code Playgroud)

或者我可能只是错误地执行此操作...如何调用方法然后检查应用于自身的属性?

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

bru*_*nde 13

如果我理解你的问题,我认为你想做的事情是不可能的......

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

为此,您必须将调用对象传递给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");
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 不,Render方法可以很好地访问typeof(HtmlForm)而不是obj.GetType(),那么你就不再需要obj了.当然,如果HtmlForm本身是私有的,那么你可能需要通过Assembly.GetExecutingAssembly().GetTypes().Where(t =>!t.IsGeneric &&!t.IsNested && t.FullName =="MyNamespace"找到它. HtmlForm")或类似的东西. (2认同)

Jos*_*rke 10

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

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);
    }

}
Run Code Online (Sandbox Code Playgroud)

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

MethodInfo.GetCurrentMethod().IsDefined(typeof(ObsoleteAttribute));
Run Code Online (Sandbox Code Playgroud)

编辑

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

如果没有这个,你就必须像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;
    }
Run Code Online (Sandbox Code Playgroud)


Jon*_*eet 5

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

  • 迭代要搜索的所有程序集
  • 迭代每个程序集中的所有类型
  • 迭代每种类型中的所有字段
  • 检查每个字段的属性是否存在

现在,如果你真的试图找出"是一个特定属性应用于一个值为'this'对象的引用的字段"那么那就更难了 - 因为你必须知道系统中每个对象的所有内容.您还应该记住,可能有两个具有相同值的字段,即引用相同的对象.在这种情况下,对象是否会被视为"可选"?

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

可能是因为我误解了你想要做的事情,但我怀疑它要么不可行,要么至少不是个好主意.你能解释一下这里的大局吗?你真的想通过这个属性实现什么?