C# 循环类型的GetFields和GetProperties?

C# 循环类型的GetFields和GetProperties?,c#,foreach,propertyinfo,C#,Foreach,Propertyinfo,这是我的密码: var fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance); foreach (FieldInfo field in fields) { //some code } var props = type.GetProperties(); foreach (PropertyInfo prop in props) { //exact same code } 我知道我可以创建一个可以调

这是我的密码:

var fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance);
foreach (FieldInfo field in fields)
{
    //some code
}

var props = type.GetProperties();
foreach (PropertyInfo prop in props)
{
    //exact same code
}
我知道我可以创建一个可以调用两次的函数,但我想做的(如果可能的话)是使用单个
foreach
。类似这样的事情(是的,代码不起作用。如果它起作用,我不会问这个问题!)

我真的觉得有一种方法,即使我知道我的解决方案远不是可编译的:(

感谢您的帮助!

如果
MemberInfo
公开的功能对循环中的您来说足够了,那么您可以将同一数组或其他可枚举项上的字段和属性连接起来,并且只迭代一次

这是可能的,因为
FieldInfo
PropertyInfo
都继承自
MemberInfo

示例代码:

var fields = typeof(DateTime).GetFields(
    BindingFlags.Public | BindingFlags.Instance);

var properties = typeof(DateTime).GetProperties(
    BindingFlags.Public | BindingFlags.Instance);

var all = fields.Cast<MemberInfo>().Concat(properties.Cast<MemberInfo>());

foreach (MemberInfo mi in all)
{
    //some code
}
var fields=typeof(DateTime).GetFields(
BindingFlags.Public | BindingFlags.Instance);
var properties=typeof(DateTime).GetProperties(
BindingFlags.Public | BindingFlags.Instance);
var all=fields.Cast().Concat(properties.Cast());
foreach(所有成员信息mi)
{
//一些代码
}

如果您对MemberInfo类公开的属性(它是FieldInfo和PropertyInfo的基础)没有意见,那么您可以执行以下操作:

var fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance).Cast<MemberInfo>();
var props = type.GetProperties().Cast<MemberInfo>();
var fieldsAndProperties = fields.Union(props);

foreach (MemberInfo mi in fieldsAndProperties)
{
...
}
var fields=type.GetFields(BindingFlags.Public | BindingFlags.Instance).Cast();
var props=type.GetProperties().Cast();
var fieldsAndProperties=fields.Union(props);
foreach(字段和属性中的MemberInfo mi)
{
...
}

要将它们放入一个循环中:

foreach (MemberInfo member in fields.Cast<MemberInfo>().Concat(props))
{ 
    //I'm 100% sure this isn't what you want
    //because you need to set value here
    //in this case, you still need to check if member is a FieldInfo/PropertyInfo 
    //and then convert it before you set the values
}
foreach(fields.Cast().Concat(props)中的MemberInfo成员)
{ 
//我百分之百肯定这不是你想要的
//因为您需要在这里设置值
//在这种情况下,您仍然需要检查成员是否为FieldInfo/PropertyInfo
//然后在设置值之前对其进行转换
}
实际上,在这里使用两个循环可能更好。首先,代码看起来更清晰,因为它们在做不同的事情,一个设置字段值,另一个用于属性。其次,寄存器缓存可能有助于使程序比一个循环快一点。

Hmmm

这种迭代是失去了字段和属性的顺序。 例如

If GetFields If get first-我们得到“testi”作为第一个成员M,通过GetProperties我们得到“tests”。 工会可能会合并他们,但秩序并没有得到维护


有什么方法可以获取字段和属性并保持它们的顺序吗?

我建议按照下面的方法遍历对象并记录对象信息

public static string ObjectToString(object obj)
{
    var sb = new StringBuilder();
    try
    {
        sb.AppendLine(obj.GetType().Name);
        foreach (var prop in obj.GetType().GetProperties())
        {
            sb.AppendLine(string.Format("{0} Property Name: {1}; Value: [{2}]; Type: {3}", "--->", prop.Name, prop.GetValue(obj, null)?.ToString(), prop.PropertyType?.FullName));
        }
        foreach (var fld in obj.GetType().GetFields())
        {
            if (!fld.FieldType.Namespace.Equals("System", StringComparison.InvariantCultureIgnoreCase) && fld.GetValue(obj) != null)
            {
                ObjectToString(fld.GetValue(obj), sb);
            }
            else
            {
                sb.AppendLine(string.Format("{0} Field Name: {1}; Value: [{2}]; Type: {3}", "--->", fld.Name, fld.GetValue(obj)?.ToString(), fld.FieldType?.FullName));
            }
        }
    }
    catch (Exception ex)
    {
        sb.AppendLine("---> Exception in ObjectToString: " + ex.Message);
    }
    return sb.ToString();
}
public static string ObjectToString(object obj, StringBuilder sb, int depth = 1)
{
    try
    {
        sb.AppendLine(string.Format("{0}{1} {2}", (depth==2?"----":""),"--->", obj.GetType().Name));
        foreach (var prop in obj.GetType().GetProperties())
        {
            sb.AppendLine(string.Format("{0} Property Name: {1}; Value: [{2}]; Type: {3}", "------->", prop.Name, prop.GetValue(obj, null)?.ToString(), prop.PropertyType?.FullName));
        }
        foreach (var fld in obj.GetType().GetFields())
        {
            //we want to avoid stake overflow and go only one more depth
            if (!fld.FieldType.Namespace.Equals("System", StringComparison.InvariantCultureIgnoreCase) && fld.GetValue(obj) != null && depth < 2)
            {
                ObjectToString(fld.GetValue(obj), sb, 2);
            }
            else
            {
                sb.AppendLine(string.Format("{0} Field Name: {1}; Value: [{2}]; Type: {3}", "------->", fld.Name, fld.GetValue(obj)?.ToString(), fld.FieldType?.FullName));
            }
        }

    }
    catch (Exception ex)
    {
        sb.AppendLine("-------> Exception in ObjectToString: depth(" + depth + ") " + ex.Message);
    }
    return sb.ToString();
}
公共静态字符串ObjectToString(objectobj)
{
var sb=新的StringBuilder();
尝试
{
sb.AppendLine(obj.GetType().Name);
foreach(obj.GetType().GetProperties()中的var prop)
{
sb.AppendLine(string.Format(“{0}属性名:{1};值:[{2}];类型:{3}”,“-->”,prop.Name,prop.GetValue(obj,null)?.ToString(),prop.PropertyType?.FullName));
}
foreach(obj.GetType().GetFields()中的变量fld)
{
如果(!fld.FieldType.Namespace.Equals(“System”,StringComparison.InvariantCultureIgnoreCase)和&fld.GetValue(obj)!=null)
{
ObjectToString(fld.GetValue(obj),sb);
}
其他的
{
sb.AppendLine(string.Format(“{0}字段名:{1};值:[{2}];类型:{3}”,“-->”,fld.Name,fld.GetValue(obj)?.ToString(),fld.FieldType?.FullName));
}
}
}
捕获(例外情况除外)
{
sb.AppendLine(“-->ObjectToString中的异常:“+ex.Message”);
}
使某人返回字符串();
}
公共静态字符串ObjectToString(对象obj,StringBuilder sb,int-depth=1)
{
尝试
{
sb.AppendLine(string.Format(“{0}{1}{2}”,(depth==2?”——:“),“-->”,obj.GetType().Name));
foreach(obj.GetType().GetProperties()中的var prop)
{
sb.AppendLine(string.Format(“{0}属性名:{1};值:[{2}];类型:{3}”,“---->”,prop.Name,prop.GetValue(obj,null)?.ToString(),prop.PropertyType?.FullName));
}
foreach(obj.GetType().GetFields()中的变量fld)
{
//我们希望避免桩溢出,只需再深入一层
如果(!fld.FieldType.Namespace.Equals(“System”,StringComparison.InvariantCultureIgnoreCase)和&fld.GetValue(obj)!=null和&depth<2)
{
ObjectToString(fld.GetValue(obj),sb,2);
}
其他的
{
sb.AppendLine(string.Format(“{0}字段名:{1};值:[{2}];类型:{3}”,“----->”,fld.Name,fld.GetValue(obj)?.ToString(),fld.FieldType?.FullName));
}
}
}
捕获(例外情况除外)
{
sb.AppendLine(“---->ObjectToString:depth(“+depth+”)+ex.Message中的异常);
}
使某人返回字符串();
}

使用反射访问成员属性的一个问题是速度太慢。 有一个很小的库,它使用一些动态生成的访问器代码,可以很快地完成这项工作。要使用它迭代所有公共字段和属性,您需要像下面这样运行简单的循环:

var ta = TypeAccessor.Create(typeof(MyClass));
foreach (var prop in ta.GetMembers())
{
    Console.WriteLine(prop.Name);

}
var instance = new MyClass();
ta[instance, prop.Name] = "myvalue";
当您需要设置任何对象实例的字段或属性值时,可以这样做:

var ta = TypeAccessor.Create(typeof(MyClass));
foreach (var prop in ta.GetMembers())
{
    Console.WriteLine(prop.Name);

}
var instance = new MyClass();
ta[instance, prop.Name] = "myvalue";
不,我只会从字段/属性获取(读取)信息!如果可以,我会试试