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

C#反射:在成员字段上查找属性,c#,reflection,attributes,field,C#,Reflection,Attributes,Field,我可能问得不对,但是您可以/如何在类本身中找到字段。。。例如 public class HtmlPart { public void Render() { //this.GetType().GetCustomAttributes(typeof(OptionalAttribute), false); } } public class HtmlForm { private HtmlPart _FirstPart = new HtmlPart(); [Option

我可能问得不对,但是您可以/如何在类本身中找到字段。。。例如

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();
}
公共类HtmlPart{
公共无效呈现(){
//this.GetType().GetCustomAttributes(typeof(OptionalAttribute),false);
}
}
公共类HtmlForm{
私有HtmlPart _FirstPart=新HtmlPart();

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

  • 迭代所有要搜索的程序集
  • 迭代每个程序集中的所有类型
  • 迭代每个类型中的所有字段
  • 检查每个字段的属性是否存在
现在,如果您真的想找出“某个特定属性是否应用于某个字段,该字段的值是对“this”对象的引用”那就更难了——因为你必须了解系统中每个对象的所有信息。你还应该记住,可能有两个字段都具有相同的值,即引用相同的对象。在这种情况下,对象是否算作“可选”

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


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

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

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

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

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

若要回答“编辑是”,可以在不知道实际类型的情况下回答。以下函数接受一个类型参数并返回具有给定属性的所有字段。某个地方的某人将知道您要搜索的类型,或者将拥有您要搜索的类型的实例

否则,您将不得不按照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;
    }
公共列表FindFields(类型,类型属性)
{
变量字段=新列表();
foreach(type.GetFields(BindingFlags.Public)中的var字段|
BindingFlags.NonPublic|
BindingFlags.Instance)
{
if(字段已定义(属性,true))
{
字段。添加(字段);
}
}
返回字段;
}

如果我正确理解了你的问题,我认为你想做的是不可能的

Render
方法中,您希望获取应用于对象的可能属性。该属性属于属于类
HtmlForm
的字段
\u SecondPart

为此,必须将调用对象传递给
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");
            }
        }
    }

感谢您的回复-现在这更像是一个实验,而不是其他任何东西。我想知道这是否可能,因为这是一种尝试获取信息的奇怪方式。感谢-这似乎是“可能的”,但我再次认为,缺少的东西太多了,它无法工作。不,渲染方法完全可以访问typeof(HtmlForm)当然,如果HtmlForm本身是私有的,那么您可能需要通过Assembly.getExecutionGassembly().GetTypes().Where(t=>!t.IsGeneric&&!t.IsNested&&t.FullName==“MyNamespace.HtmlForm”)或类似的方式找到它。