C# 如何使用反射获取对象的值列表';匹配特定类型的字段?

C# 如何使用反射获取对象的值列表';匹配特定类型的字段?,c#,reflection,C#,Reflection,请注意,为了简洁和可读性,我使用了更简单的类型、字段和方法 我已经为一个类定义了一个布尔属性,personProperty,其中我希望getter,get{}调用一个私有方法,personMethod(int arg)对在Person中定义的每个整型字段值进行调用(在本例中,\u age,\u phoneNumber)。它应该忽略所有其他类型,如readingList 这样,如果我要向Person添加另一个整数字段(或修改或删除任何Person字段名),我就不必更新personProperty的

请注意,为了简洁和可读性,我使用了更简单的类型、字段和方法

我已经为一个类定义了一个布尔属性,
personProperty
,其中我希望getter,
get{}
调用一个私有方法,
personMethod(int arg)
对在
Person
中定义的每个整型字段值进行调用(在本例中,
\u age
\u phoneNumber
)。它应该忽略所有其他类型,如
readingList

这样,如果我要向
Person
添加另一个整数字段(或修改或删除任何
Person
字段名),我就不必更新
personProperty
的定义,根据设计选择,该定义取决于
Person
类的所有整数字段(也就是说,开发人员永远不会引入一个他不希望
personMethod
运行的
int
字段)

公共类人物
{
私人互联网;
公共国际电话号码;
//受保护的国际未来国际;
字典_readingList=新字典();
公共财产
{
得到
{
// ...
bool personPropertyReturnValue;
列表结果列表=新列表();
foreach(个人列表中的int personFieldValue)
{
bool结果=personMethod(personFieldValue);
结果列表。添加(结果);
}
//使用'resultList'执行初始化personPropertyReturnValue的操作;
返回personPropertyReturnValue;
}
}
私人bool personMethod(intarg)
{
bool returnValue=true;
//执行一些操作来初始化'returnValue'`
返回值;
}
}

我需要知道我应该用什么来代替
个人列表
,以便它返回一个iterable值,该值存储在
\u age
\u phoneNumber
(以及所有其他未来的
int
,如
\u futureInt
中定义的
\u-futureInt
).

我不认为使用反射比每次添加字段时都调整属性更好,但这就是问题所在:

public class Person
{
    private int _age;
    public int _phoneNumber;
    // protected int _futureInt;
    Dictionary<string, string> _readingList = new Dictionary<string, string>();

    public Person(int age){
        _age = age;
    }

    public bool personProperty
    {
        get
        {
            List<bool> resultList = new List<bool>();
            var intFields = this.GetType().GetFields(BindingFlags.Instance | 
                                                     BindingFlags.NonPublic | 
                                                     BindingFlags.Public)
                                          .Where(f => f.FieldType == typeof(int))
                                          .Select(f => f.GetValue(this)).Cast<int>();
            foreach (int personFieldValue in intFields)
            {
                bool result = personMethod(personFieldValue);
                resultList.Add(result);
            }
            // Do stuff with `resultList` that'll initialize personPropertyReturnValue;
            bool personPropertyReturnValue = resultList.All(b => b);
            return personPropertyReturnValue;
        }
    }

    private bool personMethod(int arg)
    {
        return (arg > 0);
    }
}

希望您没有将实际电话号码存储为
int
。请注意,请尽量遵循标准,除非字段名称只是示例,否则您不应该真正使用
int
作为电话号码。@Scottannen来回答您的问题-我正在使用的数据类型,对应于
在本例中,int
在含义上类似,因此对其调用某些方法是有意义的。我可以在另一篇文章中讨论细节,但我认为讨论更适合。调用顺序并不重要,因为对每个
int
操作的方法的结果不依赖于任何以前的结果。不,更改声明顺序不会导致错误(我已经测试过)@MTV我明白。在这种情况下,我觉得几乎有义务提及它。最大的挑战之一是编写代码,以便其他人能够轻松理解和维护。在这种情况下,如果字段仅仅因为存在而产生了一些影响,那将是非常令人困惑的。重要的是能够看到一些东西并知道它的作用,并且是否已使用它。如果我们看到未使用的字段,我们会将其删除。如果我们更改了不应更改的内容,编译器会告诉我们。但在这种情况下,这些都不会发生-代码将以难以理解的方式表现出不同的行为。@MTV您不需要对此进行尝试捕获。您可以通过检查
Fi来筛选类型eldType
属性,就像我在下面所做的那样,或者通过对值调用OfType()来实现。我对LINQ不是很熟悉,因此您可以帮助我验证表达式
。选择(f=>f.GetValue(this)).Cast()
只需获取所有过滤的
FieldInfo
对象,并将其强制转换为
int
?这与
。Where
LINQ表达式是重要的表达式,似乎可以保证不会抛出
InvalidCastException
。@MTV这是正确的。但它不会强制转换
FieldInfo
对象;它强制转换由
Select
GetValue
返回的字段值。这些值属于
Object
类型,但它们是“装箱的
int
s”这就是为什么我们将它们强制转换为
int
,而不必担心
InvalidCastException
。或者,您可以去掉
Where
并使用
。选择(f=>f.GetValue(this))。of type();
直接获取
int
值。我使用了第一种方法,因为它在
字段类型上过滤,而不是在值上过滤,这允许您访问更多的值。
public class Person
{
    private int _age;
    public int _phoneNumber;
    // protected int _futureInt;
    Dictionary<string, string> _readingList = new Dictionary<string, string>();

    public Person(int age){
        _age = age;
    }

    public bool personProperty
    {
        get
        {
            List<bool> resultList = new List<bool>();
            var intFields = this.GetType().GetFields(BindingFlags.Instance | 
                                                     BindingFlags.NonPublic | 
                                                     BindingFlags.Public)
                                          .Where(f => f.FieldType == typeof(int))
                                          .Select(f => f.GetValue(this)).Cast<int>();
            foreach (int personFieldValue in intFields)
            {
                bool result = personMethod(personFieldValue);
                resultList.Add(result);
            }
            // Do stuff with `resultList` that'll initialize personPropertyReturnValue;
            bool personPropertyReturnValue = resultList.All(b => b);
            return personPropertyReturnValue;
        }
    }

    private bool personMethod(int arg)
    {
        return (arg > 0);
    }
}
var person1 = new Person(0);
Console.WriteLine(person1.personProperty);   // False

var person2 = new Person(1);
Console.WriteLine(person2.personProperty);   // False

var person3 = new Person(1) { _phoneNumber = 1 };
Console.WriteLine(person3.personProperty);   // True