C# 中使用反射获取字段的属性

发布于 2024-08-04 12:54:08 字数 1988 浏览 4 评论 0原文

我编写了一个从对象中提取字段的方法,如下所示:

private static string GetHTMLStatic(ref Object objectX, ref List<string> ExludeFields)
{
    Type objectType = objectX.GetType();
    FieldInfo[] fieldInfo = objectType.GetFields();

    foreach (FieldInfo field in fieldInfo)
    {
        if(!ExludeFields.Contains(field.Name))
        {
            DisplayOutput += GetHTMLAttributes(field);
        }                
    }

    return DisplayOutput;
}

我的类中的每个字段也有它自己的属性,在本例中我的属性称为 HTMLAttributes。在 foreach 循环内,我试图获取每个字段的属性及其各自的值。它目前看起来像这样:

private static string GetHTMLAttributes(FieldInfo field)
{
    string AttributeOutput = string.Empty;

    HTMLAttributes[] htmlAttributes = field.GetCustomAttributes(typeof(HTMLAttributes), false);

    foreach (HTMLAttributes fa in htmlAttributes)
    {
        //Do stuff with the field's attributes here.
    }

    return AttributeOutput;
}

我的属性类看起来像这样:

[AttributeUsage(AttributeTargets.Field,
                AllowMultiple = true)]
public class HTMLAttributes : System.Attribute
{
    public string fieldType;
    public string inputType;

    public HTMLAttributes(string fType, string iType)
    {
        fieldType = fType.ToString();
        inputType = iType.ToString();
    }
}

这似乎合乎逻辑,但它不会编译,我在 GetHTMLAttributes() 方法下有一条红色波浪线:

field.GetCustomAttributes(typeof(HTMLAttributes), false);

我试图从中提取属性的字段位于另一个类是这样使用的:

[HTMLAttributes("input", "text")]
public string CustomerName;

根据我的理解(或缺乏),这应该有效吗?请各位开发者扩展我的思路!

*编辑,编译器错误

无法隐式转换类型 “object[]”到“data.HTMLAttributes[]”。 存在显式转换(您是 缺少演员?)

我尝试像这样强制转换:

(HTMLAttributes)field.GetCustomAttributes(typeof(HTMLAttributes), false);

但这也不起作用,我收到此编译器错误:

无法将类型“object[]”转换为 'data.HTMLAttributes'

I wrote a method that extracts fields from an object like this:

private static string GetHTMLStatic(ref Object objectX, ref List<string> ExludeFields)
{
    Type objectType = objectX.GetType();
    FieldInfo[] fieldInfo = objectType.GetFields();

    foreach (FieldInfo field in fieldInfo)
    {
        if(!ExludeFields.Contains(field.Name))
        {
            DisplayOutput += GetHTMLAttributes(field);
        }                
    }

    return DisplayOutput;
}

Each field in my class also has it's own attributes, in this case my attribute is called HTMLAttributes. Inside the foreach loop I'm trying to get the attributes for each field and their respective values. It currently looks like this:

private static string GetHTMLAttributes(FieldInfo field)
{
    string AttributeOutput = string.Empty;

    HTMLAttributes[] htmlAttributes = field.GetCustomAttributes(typeof(HTMLAttributes), false);

    foreach (HTMLAttributes fa in htmlAttributes)
    {
        //Do stuff with the field's attributes here.
    }

    return AttributeOutput;
}

My attributes class looks like this:

[AttributeUsage(AttributeTargets.Field,
                AllowMultiple = true)]
public class HTMLAttributes : System.Attribute
{
    public string fieldType;
    public string inputType;

    public HTMLAttributes(string fType, string iType)
    {
        fieldType = fType.ToString();
        inputType = iType.ToString();
    }
}

This seems logical but it won't compile, I have a red squiggly line in the GetHTMLAttributes() method under:

field.GetCustomAttributes(typeof(HTMLAttributes), false);

The field I'm trying to extract the attributes from is in another class used like this:

[HTMLAttributes("input", "text")]
public string CustomerName;

From my understanding (or lack thereof) this should work? Please expand my mind fellow developers!

*Edit, compiler error:

Cannot implicitly convert type
'object[]' to 'data.HTMLAttributes[]'.
An explicit conversion exists (are you
missing a cast?)

I have tried casting it like this:

(HTMLAttributes)field.GetCustomAttributes(typeof(HTMLAttributes), false);

But that also doesn't work, I get this compiler error:

Cannot convert type 'object[]' to
'data.HTMLAttributes'

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

森林散布 2024-08-11 12:54:08

GetCustomAttributes 方法返回一个 object[],而不是 HTMLAttributes[]。它返回 object[] 的原因是它从 1.0 开始就存在,在 .NET 泛型出现之前。

您应该手动将返回值中的每个项目强制转换为 HTMLAttributes

要修复您的代码,您只需将该行更改为:

object[] htmlAttributes = field.GetCustomAttributes(typeof(HTMLAttributes), false);

foreach 将为您处理转换。

更新:

不应该将返回的数组强制转换为HTMLAttributes[]。返回值不是 HTMLAttributes[]。它是一个包含 HTMLAttributes 类型元素的 object[]。如果您想要一个 HTMLAttribute[] 类型对象(在此特定代码片段中不需要,foreach 就足够了),您应该将数组的每个元素单独转换为HTMLAttribute;也许使用 LINQ:

HTMLAttributes[] htmlAttributes = returnValue.Cast<HTMLAttributes>().ToArray();

GetCustomAttributes method returns an object[], not HTMLAttributes[]. The reason it returns object[] is that it has been there since 1.0, before .NET generics see the light of day.

You should manually cast each item in the return value to HTMLAttributes.

To fix your code, you simply need to change the line to:

object[] htmlAttributes = field.GetCustomAttributes(typeof(HTMLAttributes), false);

foreach will take care of the cast for you.

Update:

You shouldn't cast the returned array to HTMLAttributes[]. The return value is not HTMLAttributes[]. It's an object[] containing elements of type HTMLAttributes. If you want a HTMLAttribute[] typed object (which you don't need in this specific code snippet, foreach would suffice), you should cast each element of array individually to HTMLAttribute; perhaps using LINQ:

HTMLAttributes[] htmlAttributes = returnValue.Cast<HTMLAttributes>().ToArray();
那一片橙海, 2024-08-11 12:54:08

如果一个类 Person 用像这样的属性装饰,

public class Person
{
    [HTMLAttributes("input", "text")]
    public string CustomerName;

    [HTMLAttributes("string","charArray")]
    public string FirstName  = "FirstName";
        
    [HTMLAttributes("string","object")]
    public string LastName = "LastName";
}

你首先需要过滤 &找到所有用 HTMLAttributes 装饰的 Fields,这可以使用 linq 完成

obj.GetType().GetFields()
.Where(_ => _.GetCustomAttributes(typeof(HTMLAttributes), true).Length >= 1  && _.Name == name)

然后您可以cast 它以供您使用

GetCustomAttributes(typeof(HTMLAttributes), true).Cast<HTMLAttributes>()

解决方案

如下 < code>Extension Method 被编码为对任何对象执行繁重的工作。

public static class ObjectExtended //ExtensionClass
{
    public static T ReadAttribute<T>(this object obj,string name)
    {
        var all= obj.GetType().GetFields()
        .Where(_ => _.GetCustomAttributes(typeof(T), true).Length >= 1  && _.Name == name).FirstOrDefault();

        var attrib = all.GetCustomAttributes(typeof(T), true)
        .Cast<T>().FirstOrDefault();;
        
        return attrib;
    }
}

示例:

由于它是扩展方法,因此可在对象旁边使用。所以在 main 中如果我们写:

void Main()
{
    var p = new Person();
    var attrib = p.ReadAttribute<HTMLAttributes>("CustomerName").Dump();
    
    attrib.fieldType.Dump();
    attrib.inputType.Dump();
}

你可以读取属性值,如下所示:
输入图片此处描述

注意:Dump() 可以替换为 Console.Write()Console.WriteLine() 在控制台中运行时

If a class Person is decorated with Attributes like

public class Person
{
    [HTMLAttributes("input", "text")]
    public string CustomerName;

    [HTMLAttributes("string","charArray")]
    public string FirstName  = "FirstName";
        
    [HTMLAttributes("string","object")]
    public string LastName = "LastName";
}

You first needs to filter & find all the Fields which are decorated with HTMLAttributes, which can be done with linq

obj.GetType().GetFields()
.Where(_ => _.GetCustomAttributes(typeof(HTMLAttributes), true).Length >= 1  && _.Name == name)

Then you can cast it for your use with

GetCustomAttributes(typeof(HTMLAttributes), true).Cast<HTMLAttributes>()

Solution

The following Extension Method is coded to do that heavy work on any object.

public static class ObjectExtended //ExtensionClass
{
    public static T ReadAttribute<T>(this object obj,string name)
    {
        var all= obj.GetType().GetFields()
        .Where(_ => _.GetCustomAttributes(typeof(T), true).Length >= 1  && _.Name == name).FirstOrDefault();

        var attrib = all.GetCustomAttributes(typeof(T), true)
        .Cast<T>().FirstOrDefault();;
        
        return attrib;
    }
}

Example:

Since it is an extension method itis available next to the object. So in the main if we write:

void Main()
{
    var p = new Person();
    var attrib = p.ReadAttribute<HTMLAttributes>("CustomerName").Dump();
    
    attrib.fieldType.Dump();
    attrib.inputType.Dump();
}

and you can read the attribute value as below:
enter image description here

Note: Dump() can be replace with Console.Write() or Console.WriteLine() when running in console

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文